import { prisma } from '@/lib/db'
import { getMappingByDiscordId, hasCompletedFirstJoin } from './identifier-mapping-service'
import { auditLog } from '@/lib/audit'
import type { Role } from '@prisma/client'

// ==========================================
// PLAYER ACCESS SERVICE
// ==========================================
// Handles access control based on first-join status and user roles
// Implements the core access rule: normal players must join server first

export interface AccessCheckResult {
  hasAccess: boolean
  reason: 'first_join_required' | 'access_granted' | 'superadmin_no_data'
  isSuperadmin: boolean
  hasPlayerData: boolean
  mapping?: {
    discordId: string
    firstJoinAt: Date
    lastSeenAt: Date
    gameIdentifier: string | null
    characterId: string | null
  } | null
  message?: string
}

/**
 * Check if a user has access to the UCP based on first-join rules
 * 
 * Rules:
 * 1. Normal users (USER, ADMIN) must have completed first join to access
 * 2. Superadmins always have access, but may have limited data
 */
export async function checkPlayerAccess(
  discordId: string,
  role: Role
): Promise<AccessCheckResult> {
  const isSuperadmin = role === 'SUPERADMIN'
  
  // Get the identifier mapping
  const mapping = await getMappingByDiscordId(discordId)
  const hasPlayerData = mapping !== null

  // Superadmin always has access
  if (isSuperadmin) {
    if (!hasPlayerData) {
      // No audit log needed - this is just an access check, not a change
      return {
        hasAccess: true,
        reason: 'superadmin_no_data',
        isSuperadmin: true,
        hasPlayerData: false,
        mapping: null,
        message: 'You have not joined the server yet. Admin features are available, but personal player statistics cannot be displayed.',
      }
    }

    return {
      hasAccess: true,
      reason: 'access_granted',
      isSuperadmin: true,
      hasPlayerData: true,
      mapping: mapping ? {
        discordId: mapping.discordId,
        firstJoinAt: mapping.firstJoinAt,
        lastSeenAt: mapping.lastSeenAt,
        gameIdentifier: mapping.gameIdentifier,
        characterId: mapping.characterId,
      } : null,
    }
  }

  // Normal users must have completed first join
  if (!hasPlayerData) {
    // No audit log needed - this is just an access check, not a change
    return {
      hasAccess: false,
      reason: 'first_join_required',
      isSuperadmin: false,
      hasPlayerData: false,
      mapping: null,
      message: 'You need to join the FiveM server at least once before you can use this panel. Your Discord account will be linked automatically on your first join.',
    }
  }

  return {
    hasAccess: true,
    reason: 'access_granted',
    isSuperadmin: false,
    hasPlayerData: true,
    mapping: mapping ? {
      discordId: mapping.discordId,
      firstJoinAt: mapping.firstJoinAt,
      lastSeenAt: mapping.lastSeenAt,
      gameIdentifier: mapping.gameIdentifier,
      characterId: mapping.characterId,
    } : null,
  }
}

/**
 * Get the access status for the current user (for API routes)
 */
export async function getAccessStatus(userId: string) {
  const user = await prisma.user.findUnique({
    where: { id: userId },
  })

  if (!user) {
    return {
      error: 'User not found',
      hasAccess: false,
    }
  }

  return checkPlayerAccess(user.discordId, user.role)
}

/**
 * Check if a user should see player statistics widgets
 */
export async function shouldShowPlayerStats(
  discordId: string,
  role: Role
): Promise<boolean> {
  const mapping = await getMappingByDiscordId(discordId)
  return mapping !== null
}

/**
 * Get detailed player link status for admin inspection
 */
export async function getPlayerLinkStatus(discordId: string) {
  const mapping = await getMappingByDiscordId(discordId)
  
  if (!mapping) {
    return {
      isLinked: false,
      hasFirstJoin: false,
      details: null,
    }
  }

  return {
    isLinked: true,
    hasFirstJoin: true,
    details: {
      discordId: mapping.discordId,
      license: mapping.license,
      steam: mapping.steam,
      fivem: mapping.fivem,
      gameIdentifier: mapping.gameIdentifier,
      characterId: mapping.characterId,
      firstJoinAt: mapping.firstJoinAt,
      lastSeenAt: mapping.lastSeenAt,
      isVerified: mapping.isVerified,
    },
  }
}

/**
 * Admin function to manually link a Discord account to player data
 */
export async function manuallyLinkPlayer(
  discordId: string,
  gameIdentifier: string,
  performedBy: string
): Promise<{ success: boolean; error?: string }> {
  try {
    const existing = await getMappingByDiscordId(discordId)

    if (existing) {
      await prisma.identifierMapping.update({
        where: { discordId },
        data: {
          gameIdentifier,
          lastSeenAt: new Date(),
        },
      })
    } else {
      await prisma.identifierMapping.create({
        data: {
          discordId,
          gameIdentifier,
          firstJoinAt: new Date(),
          lastSeenAt: new Date(),
        },
      })
    }

    await auditLog({
      userId: performedBy,
      action: 'MANUAL_PLAYER_LINK',
      category: 'ADMIN',
      details: {
        discordId,
        gameIdentifier,
        hadExisting: !!existing,
      },
    })

    return { success: true }
  } catch (error) {
    console.error('[PlayerAccess] Error manually linking player:', error)
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error',
    }
  }
}
