import { NextResponse } from 'next/server';
import { db } from '@/db/connection';
import { employees, candidates, votes, voteRecords, branches, settings } from '@/db/schema';
import { eq, and, count, sql } from 'drizzle-orm';
import { getAuthUser } 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/results ====================
export async function GET(request: Request) {
  try {
    const user = getAuthUser(request);

    // Check results visibility
    const resultsVisibleStr = await getSetting('resultsVisible');
    const resultsVisible = resultsVisibleStr === 'true';

    // If results not visible, only admin can see
    if (!resultsVisible && (!user || !user.isAdmin)) {
      return NextResponse.json(
        {
          visible: false,
          branches: [],
          totalVotes: 0,
          totalVoters: 0,
          totalEligibleVoters: 0,
        }
      );
    }

    // Get vote counts grouped by candidate, joined with candidate/employee/branch info
    const voteResults = await db
      .select({
        candidateId: votes.candidateId,
        branchId: votes.branchId,
        voteCount: count(),
        // Candidate details
        employeeId: candidates.employeeId,
        position: candidates.position,
        // Employee name
        name: employees.name,
        // Branch info
        branchName: branches.name,
        branchCode: branches.code,
      })
      .from(votes)
      .innerJoin(candidates, eq(votes.candidateId, candidates.id))
      .innerJoin(employees, eq(candidates.employeeId, employees.id))
      .innerJoin(branches, eq(votes.branchId, branches.id))
      .groupBy(votes.candidateId, votes.branchId);

    // Organize results by branch
    const branchMap = new Map<
      string,
      {
        branchId: string;
        branchName: string;
        branchCode: string;
        candidates: {
          candidateId: string;
          employeeId: string;
          name: string;
          position: string | null;
          voteCount: number;
        }[];
      }
    >();

    let totalVotes = 0;

    for (const row of voteResults) {
      totalVotes += row.voteCount;

      if (!branchMap.has(row.branchId)) {
        branchMap.set(row.branchId, {
          branchId: row.branchId,
          branchName: row.branchName,
          branchCode: row.branchCode,
          candidates: [],
        });
      }

      const branch = branchMap.get(row.branchId)!;
      branch.candidates.push({
        candidateId: row.candidateId,
        employeeId: row.employeeId,
        name: row.name,
        position: row.position,
        voteCount: row.voteCount,
      });
    }

    // Also include branches that have approved candidates but no votes yet
    const allCandidatesWithBranch = await db
      .select({
        candidateId: candidates.id,
        employeeId: candidates.employeeId,
        position: candidates.position,
        name: employees.name,
        branchId: candidates.branchId,
        branchName: branches.name,
        branchCode: branches.code,
      })
      .from(candidates)
      .innerJoin(employees, eq(candidates.employeeId, employees.id))
      .innerJoin(branches, eq(candidates.branchId, branches.id))
      .where(eq(candidates.isApproved, true));

    for (const row of allCandidatesWithBranch) {
      if (!branchMap.has(row.branchId)) {
        branchMap.set(row.branchId, {
          branchId: row.branchId,
          branchName: row.branchName,
          branchCode: row.branchCode,
          candidates: [],
        });
      }

      const branch = branchMap.get(row.branchId)!;
      const alreadyExists = branch.candidates.some(
        (c) => c.candidateId === row.candidateId
      );
      if (!alreadyExists) {
        branch.candidates.push({
          candidateId: row.candidateId,
          employeeId: row.employeeId,
          name: row.name,
          position: row.position,
          voteCount: 0,
        });
      }
    }

    // Count total voters (from voteRecords)
    const voterCountResult = await db
      .select({ total: count() })
      .from(voteRecords);

    const totalVoters = voterCountResult[0]?.total ?? 0;

    // Count total eligible voters (active employees)
    const eligibleCountResult = await db
      .select({ total: count() })
      .from(employees)
      .where(eq(employees.isActive, true));

    const totalEligibleVoters = eligibleCountResult[0]?.total ?? 0;

    // Convert branchMap to sorted array
    const branchesArray = Array.from(branchMap.values()).sort((a, b) =>
      a.branchCode.localeCompare(b.branchCode)
    );

    // Sort candidates within each branch by vote count (descending)
    for (const branch of branchesArray) {
      branch.candidates.sort((a, b) => b.voteCount - a.voteCount);
    }

    return NextResponse.json({
      visible: true,
      branches: branchesArray,
      totalVotes,
      totalVoters,
      totalEligibleVoters,
    });
  } catch (error) {
    console.error('GET /api/results error:', error);
    return NextResponse.json(
      { success: false, error: 'เกิดข้อผิดพลาดในระบบ' },
      { status: 500 }
    );
  }
}
