import { Router } from 'express';
import { z } from 'zod';
import { requireAuth, type AuthenticatedRequest } from './auth';
import { pool } from './db';
import { authorizeJourney } from './familyJourney';

export const familyDecisionRouter = Router();

familyDecisionRouter.get('/journeys/:id/decision', requireAuth,
  async (request: AuthenticatedRequest, response) => {
    const access = await authorizeJourney(request, response, 'participantRead');
    if (!access) return;
    const result = await pool.query(
      `SELECT d.id, d.status, d.outcome, d.created_at AS "createdAt",
         mine.choice AS "myChoice", mine.private_notes AS "myPrivateNotes",
         (SELECT COUNT(*)::int FROM participant_decisions all_decisions
          WHERE all_decisions.round_id=d.id) AS "submittedCount"
       FROM decision_rounds d
       LEFT JOIN participant_decisions mine ON mine.round_id=d.id AND mine.user_id=$2
       WHERE d.journey_id=$1 ORDER BY d.created_at DESC LIMIT 1`,
      [access.id, request.authUser!.id],
    );
    response.json({ decision: result.rows[0] ?? null });
  });

const decisionSchema = z.object({
  choice: z.enum(['continue', 'second_session', 'extend_time', 'apologize']),
  privateNotes: z.string().max(2000).default(''),
});

familyDecisionRouter.post('/journeys/:id/decision', requireAuth,
  async (request: AuthenticatedRequest, response) => {
    const access = await authorizeJourney(request, response, 'participant');
    if (!access) return;
    const parsed = decisionSchema.safeParse(request.body);
    if (!parsed.success) {
      response.status(400).json({ error: 'Invalid decision' }); return;
    }
    const client = await pool.connect();
    try {
      await client.query('BEGIN');
      const active = await client.query<{ id: string }>(
        "SELECT id FROM decision_rounds WHERE journey_id=$1 AND status='open' FOR UPDATE",
        [access.id],
      );
      const roundId = active.rows[0]?.id;
      if (!roundId) {
        await client.query('ROLLBACK');
        response.status(409).json({ error: 'No active decision round' }); return;
      }
      const existing = await client.query(
        'SELECT 1 FROM participant_decisions WHERE round_id=$1 AND user_id=$2',
        [roundId, request.authUser!.id],
      );
      if (existing.rowCount) {
        await client.query('ROLLBACK');
        response.status(409).json({ error: 'Decision already submitted' }); return;
      }
      await client.query(
        `INSERT INTO participant_decisions (round_id, user_id, choice, private_notes)
         VALUES ($1, $2, $3, $4)`,
        [roundId, request.authUser!.id, parsed.data.choice, parsed.data.privateNotes],
      );
      const choices = await client.query<{ choice: string }>(
        'SELECT choice FROM participant_decisions WHERE round_id=$1', [roundId],
      );
      let outcome: string | null = null;
      if (choices.rowCount === 2) {
        const values = choices.rows.map((row) => row.choice);
        outcome = values.includes('apologize') ? 'closed'
          : values.includes('second_session') ? 'second_session'
            : values.includes('extend_time') ? 'more_time' : 'continue';
        await client.query(
          "UPDATE decision_rounds SET status='resolved', outcome=$1, resolved_at=NOW() WHERE id=$2",
          [outcome, roundId],
        );
        if (outcome === 'closed') {
          await client.query("UPDATE journeys SET status='closed', updated_at=NOW() WHERE id=$1", [access.id]);
          await client.query('DELETE FROM journey_contact_grants WHERE journey_id=$1', [access.id]);
          await client.query("UPDATE family_invitations SET status='revoked' WHERE journey_id=$1 AND status<>'revoked'", [access.id]);
          await client.query('UPDATE journey_memberships SET is_active=FALSE WHERE journey_id=$1', [access.id]);
        }
      }
      await client.query(
        "INSERT INTO audit_events (user_id, event_type, details) VALUES ($1, 'private_decision_submitted', $2::jsonb)",
        [request.authUser!.id, JSON.stringify({ roundId, journeyId: access.id })],
      );
      await client.query('COMMIT');
      response.json({ submitted: true, outcome });
    } catch (error) {
      await client.query('ROLLBACK');
      throw error;
    } finally {
      client.release();
    }
  });
