import { NextResponse } from 'next/server';
import { db } from '@/db/connection';
import { employees, candidates, votes, voteRecords, branches, settings } from '@/db/schema';
import { eq, and, count } from 'drizzle-orm';
import { getAuthUser, generateId } from '@/lib/auth';

// Helper: get a setting value by key
async function getSetting(key: string): Promise<string | null> {
  const result = await db
    .select({ value: settings.value })
    .from(settings)
    .where(eq(settings.key, key))
    .limit(1);
  return result[0]?.value ?? null;
}

// ==================== GET /api/vote ====================
export async function GET(request: Request) {
  try {
    const user = getAuthUser(request);
    if (!user) {
      return NextResponse.json(
        { success: false, error: 'กรุณาเข้าสู่ระบบ' },
        { status: 401 }
      );
    }

    // Fetch settings
    const [maxVotesStr, votingStartDateStr, votingEndDateStr, votingEnabledStr] =
      await Promise.all([
        getSetting('maxVotesPerPerson'),
        getSetting('votingStartDate'),
        getSetting('votingEndDate'),
        getSetting('votingEnabled'),
      ]);

    const maxVotes = parseInt(maxVotesStr || '1', 10);
    const votingStartDate = votingStartDateStr ? new Date(votingStartDateStr) : null;
    const votingEndDate = votingEndDateStr ? new Date(votingEndDateStr) : null;
    const votingEnabled = votingEnabledStr === 'true';

    // Check if within voting period
    const now = new Date();
    const isWithinPeriod =
      votingStartDate && votingEndDate
        ? now >= votingStartDate && now <= votingEndDate
        : true;

    // Get user's vote record
    const voteRecordResult = await db
      .select({ voteCount: voteRecords.voteCount })
      .from(voteRecords)
      .where(eq(voteRecords.employeeId, user.dbId))
      .limit(1);

    const voteCount = voteRecordResult[0]?.voteCount ?? 0;

    // Get user's branch info
    const branchResult = await db
      .select({
        id: branches.id,
        name: branches.name,
        code: branches.code,
      })
      .from(branches)
      .where(eq(branches.id, user.branchId))
      .limit(1);

    const branch = branchResult[0] ?? { id: user.branchId, name: user.branchName, code: '' };

    // Get candidates from user's branch only, joined with employees for name
    const candidateList = await db
      .select({
        id: candidates.id,
        name: employees.name,
        position: candidates.position,
        statement: candidates.statement,
        photoUrl: candidates.photoUrl,
        employeeId: candidates.employeeId,
      })
      .from(candidates)
      .innerJoin(employees, eq(candidates.employeeId, employees.id))
      .where(
        and(
          eq(candidates.branchId, user.branchId),
          eq(candidates.isApproved, true)
        )
      );

    const canVote = votingEnabled && isWithinPeriod && voteCount < maxVotes;

    return NextResponse.json({
      canVote,
      voteCount,
      maxVotes,
      votingEnabled,
      votingStartDate: votingStartDateStr || '',
      votingEndDate: votingEndDateStr || '',
      isWithinPeriod,
      branch,
      candidates: candidateList,
    });
  } catch (error) {
    console.error('GET /api/vote error:', error);
    return NextResponse.json(
      { success: false, error: 'เกิดข้อผิดพลาดในระบบ' },
      { status: 500 }
    );
  }
}

// ==================== POST /api/vote ====================
export async function POST(request: Request) {
  try {
    const user = getAuthUser(request);
    if (!user) {
      return NextResponse.json(
        { success: false, error: 'กรุณาเข้าสู่ระบบ' },
        { status: 401 }
      );
    }

    const body = await request.json();
    const { candidateIds } = body as { candidateIds: string[] };

    // Validate candidateIds is a non-empty array
    if (!Array.isArray(candidateIds) || candidateIds.length === 0) {
      return NextResponse.json(
        { success: false, error: 'กรุณาเลือกผู้สมัครอย่างน้อย 1 คน' },
        { status: 400 }
      );
    }

    // Check for duplicate candidateIds
    const uniqueIds = new Set(candidateIds);
    if (uniqueIds.size !== candidateIds.length) {
      return NextResponse.json(
        { success: false, error: 'มีการเลือกผู้สมัครซ้ำกัน' },
        { status: 400 }
      );
    }

    // Fetch settings
    const [maxVotesStr, votingStartDateStr, votingEndDateStr, votingEnabledStr] =
      await Promise.all([
        getSetting('maxVotesPerPerson'),
        getSetting('votingStartDate'),
        getSetting('votingEndDate'),
        getSetting('votingEnabled'),
      ]);

    const maxVotes = parseInt(maxVotesStr || '1', 10);
    const votingEnabled = votingEnabledStr === 'true';
    const votingStartDate = votingStartDateStr ? new Date(votingStartDateStr) : null;
    const votingEndDate = votingEndDateStr ? new Date(votingEndDateStr) : null;

    // Check voting is enabled
    if (!votingEnabled) {
      return NextResponse.json(
        { success: false, error: 'การเลือกตั้งยังไม่เปิดให้ลงคะแนน' },
        { status: 403 }
      );
    }

    // Check within voting period
    const now = new Date();
    const isWithinPeriod =
      votingStartDate && votingEndDate
        ? now >= votingStartDate && now <= votingEndDate
        : true;

    if (!isWithinPeriod) {
      return NextResponse.json(
        { success: false, error: 'ไม่อยู่ในช่วงเวลาที่กำหนดการเลือกตั้ง' },
        { status: 403 }
      );
    }

    // Get user's current vote record
    const voteRecordResult = await db
      .select({ voteCount: voteRecords.voteCount })
      .from(voteRecords)
      .where(eq(voteRecords.employeeId, user.dbId))
      .limit(1);

    const currentVoteCount = voteRecordResult[0]?.voteCount ?? 0;
    const newTotalVoteCount = currentVoteCount + candidateIds.length;

    // Check max votes not exceeded
    if (newTotalVoteCount > maxVotes) {
      return NextResponse.json(
        {
          success: false,
          error: `คุณลงคะแนนได้สูงสุด ${maxVotes} คะแนน (ลงไปแล้ว ${currentVoteCount} คะแนน)`,
        },
        { status: 400 }
      );
    }

    // CRITICAL: Check ALL candidates belong to the user's branch
    const validCandidates = await db
      .select({ id: candidates.id })
      .from(candidates)
      .where(
        and(
          eq(candidates.branchId, user.branchId),
          eq(candidates.isApproved, true)
        )
      );

    const validCandidateIds = new Set(validCandidates.map((c) => c.id));

    for (const candidateId of candidateIds) {
      if (!validCandidateIds.has(candidateId)) {
        return NextResponse.json(
          { success: false, error: 'ผู้สมัครไม่อยู่ในสาขาของคุณ' },
          { status: 400 }
        );
      }
    }

    // Insert anonymous votes (NO voter info stored in votes table)
    for (const candidateId of candidateIds) {
      await db.insert(votes).values({
        id: generateId(),
        candidateId,
        branchId: user.branchId,
        votedAt: new Date(),
      });
    }

    // Update or insert voteRecord
    if (voteRecordResult.length > 0) {
      // Existing record — increment voteCount
      await db
        .update(voteRecords)
        .set({
          voteCount: newTotalVoteCount,
          updatedAt: new Date(),
        })
        .where(eq(voteRecords.employeeId, user.dbId));
    } else {
      // No record yet — create one
      await db.insert(voteRecords).values({
        id: generateId(),
        employeeId: user.dbId,
        voteCount: candidateIds.length,
        updatedAt: new Date(),
      });
    }

    return NextResponse.json({
      success: true,
      voteCount: newTotalVoteCount,
    });
  } catch (error) {
    console.error('POST /api/vote error:', error);
    return NextResponse.json(
      { success: false, error: 'เกิดข้อผิดพลาดในระบบ' },
      { status: 500 }
    );
  }
}
