import { Router } from 'express';
import { z } from 'zod';
import { requireAdmin, requireAuth, type AuthenticatedRequest } from './auth';
import { pool } from './db';
import { decryptSensitive } from './privacy';
import { autoAssignGuardiansForCandidate } from './autoGuardianSelection';
import { notifyUsers } from './notifications';

export const guardianAdminReviewsRouter = Router();

guardianAdminReviewsRouter.get('/admin/guardians/:id/details', requireAuth, requireAdmin,
  async (request, response) => {
    const id = z.uuid().safeParse(request.params.id);
    if (!id.success) { response.status(400).json({ error: 'Invalid guardian ID' }); return; }
    const guardian = await pool.query(
      `SELECT id,display_name AS "displayName",email,username,is_active AS "isActive",
              created_at AS "createdAt",deleted_at AS "deletedAt"
       FROM users WHERE id=$1 AND role='user' AND account_type IN ('candidate','guardian')
         AND EXISTS (SELECT 1 FROM guardian_invitations i WHERE i.accepted_by=users.id)`,
      [id.data],
    );
    if (!guardian.rows[0]) { response.status(404).json({ error: 'Guardian account not found' }); return; }
    const links = await pool.query(
      `SELECT i.id,i.status,i.phone_encrypted AS "phoneEncrypted",
              i.phone_last_four AS "phoneLastFour",i.common_contact_count AS "commonContactCount",
              i.candidate_synced_at AS "candidateSyncedAt",i.guardian_synced_at AS "guardianSyncedAt",
              i.created_at AS "createdAt",i.completed_at AS "completedAt",
              i.admin_note AS "adminNote",i.reviewed_at AS "reviewedAt",i.reviewed_by AS "reviewedBy",
              candidate.id AS "candidateUserId",candidate.display_name AS "candidateName",
              candidate.username AS "candidateUsername",reviewer.display_name AS "reviewerName"
       FROM guardian_invitations i
       JOIN users candidate ON candidate.id=i.candidate_user_id
       LEFT JOIN users reviewer ON reviewer.id=i.reviewed_by
       WHERE i.accepted_by=$1 ORDER BY i.created_at DESC`,
      [id.data],
    );
    const detailedLinks = await Promise.all(links.rows.map(async ({ phoneEncrypted, ...link }) => {
      const verificationMethod = link.reviewedBy ? 'admin'
        : link.status === 'verified' && link.commonContactCount >= 5 ? 'contacts' : 'pending';
      const evidence = verificationMethod === 'contacts' ? await pool.query(
        `SELECT candidate_name_encrypted AS "candidateNameEncrypted",
                candidate_phone_encrypted AS "candidatePhoneEncrypted",
                guardian_name_encrypted AS "guardianNameEncrypted",
                guardian_phone_encrypted AS "guardianPhoneEncrypted"
         FROM guardian_contact_matches WHERE invitation_id=$1 ORDER BY contact_digest LIMIT 5`,
        [link.id],
      ) : { rows: [] };
      return {
        ...link,
        phone: phoneEncrypted ? decryptSensitive(phoneEncrypted) : null,
        verificationMethod,
        matchedContacts: evidence.rows.map((item) => ({
          candidateName: decryptSensitive(item.candidateNameEncrypted),
          candidatePhone: decryptSensitive(item.candidatePhoneEncrypted),
          guardianName: decryptSensitive(item.guardianNameEncrypted),
          guardianPhone: decryptSensitive(item.guardianPhoneEncrypted),
        })),
      };
    }));
    response.json({ guardian: guardian.rows[0], links: detailedLinks });
  });

guardianAdminReviewsRouter.get('/admin/guardian-links', requireAuth, requireAdmin,
  async (_request, response) => {
    const result = await pool.query(
      `SELECT i.id,i.candidate_user_id AS "candidateUserId",c.display_name AS "candidateName",
              i.accepted_by AS "guardianUserId",g.display_name AS "guardianName",
              i.phone_encrypted AS "phoneEncrypted",i.phone_last_four AS "phoneLastFour",
              i.status,i.common_contact_count AS "commonContactCount",
              i.candidate_synced_at AS "candidateSyncedAt",i.guardian_synced_at AS "guardianSyncedAt",
              i.admin_note AS "adminNote",i.created_at AS "createdAt",i.reviewed_at AS "reviewedAt"
       FROM guardian_invitations i
       JOIN users c ON c.id=i.candidate_user_id
       LEFT JOIN users g ON g.id=i.accepted_by
       WHERE i.status IN ('registered','verified','failed')
       ORDER BY CASE i.status WHEN 'registered' THEN 0 ELSE 1 END,i.created_at DESC`,
    );
    response.json({ links: result.rows.map(({ phoneEncrypted, ...item }) => ({
      ...item,
      phone: phoneEncrypted ? decryptSensitive(phoneEncrypted) : null,
    })) });
  });

guardianAdminReviewsRouter.patch('/admin/guardian-links/:id', requireAuth, requireAdmin,
  async (request: AuthenticatedRequest, response) => {
    const id = z.uuid().safeParse(request.params.id);
    const parsed = z.object({
      decision: z.enum(['approved', 'rejected']),
      note: z.string().trim().max(1000).default(''),
      contactConfirmed: z.literal(true),
    }).safeParse(request.body);
    if (!id.success || !parsed.success) {
      response.status(400).json({ error: 'A confirmed phone review is required' }); return;
    }
    const status = parsed.data.decision === 'approved' ? 'verified' : 'failed';
    const result = await pool.query<{ candidate_user_id: string; accepted_by: string | null }>(
      `UPDATE guardian_invitations
       SET status=$1,admin_note=$2,reviewed_by=$3,reviewed_at=NOW(),
           contact_confirmed_at=NOW(),completed_at=NOW()
       WHERE id=$4 AND status='registered' AND ($1='failed' OR phone_encrypted IS NOT NULL)
       RETURNING candidate_user_id,accepted_by`,
      [status, parsed.data.note, request.authUser!.id, id.data],
    );
    if (!result.rows[0]) { response.status(404).json({ error: 'Pending guardian review not found' }); return; }
    await pool.query(
      "INSERT INTO audit_events (user_id,event_type,details) VALUES ($1,'guardian_link_reviewed',$2::jsonb)",
      [request.authUser!.id, JSON.stringify({ guardianLinkId: id.data, decision: parsed.data.decision,
        candidateUserId: result.rows[0].candidate_user_id, guardianUserId: result.rows[0].accepted_by })],
    );
    if (status === 'verified') await autoAssignGuardiansForCandidate(result.rows[0].candidate_user_id);
    await notifyUsers([result.rows[0].candidate_user_id,
      ...(result.rows[0].accepted_by ? [result.rows[0].accepted_by] : [])], {
      type: 'guardian_reviewed',
      title: status === 'verified' ? 'تم توثيق وليّ الأمر' : 'تعذر توثيق وليّ الأمر',
      body: status === 'verified'
        ? 'اكتملت مراجعة الربط وأصبح وليّ الأمر موثقًا.'
        : 'لم يكتمل التحقق من الربط. راجع قسم وليّ الأمر لمعرفة الخطوة التالية.',
      dedupeKey: `guardian-reviewed:${id.data}:${status}`,
    });
    response.json({ reviewed: true });
  });
