import { NextRequest, NextResponse } from "next/server";
import { sql } from "@/db";
import { requireFamily } from "@/lib/auth";

// ─── IST helpers (server-side) ────────────────────────────────────────────────
const IST_OFFSET_MS = 5.5 * 60 * 60 * 1000; // UTC +5:30

function getISTDate(): string {
  return new Date().toLocaleDateString("sv-SE", { timeZone: "Asia/Kolkata" }); // YYYY-MM-DD
}

function getISTHour(): number {
  const str = new Intl.DateTimeFormat("en-IN", { timeZone: "Asia/Kolkata", hour: "numeric", hour12: false }).format(new Date());
  const h = parseInt(str, 10);
  return h === 24 ? 0 : h;
}

/** Monday of the current IST week (for weekly garment nudge slot) */
function getISTWeekMonday(): string {
  const istNow = new Date(Date.now() + IST_OFFSET_MS);
  const dow    = istNow.getUTCDay(); // 0=Sun … 6=Sat
  const mon    = new Date(istNow.getTime() - ((dow === 0 ? 6 : dow - 1) * 86_400_000));
  return mon.toISOString().slice(0, 10);
}

// ─── IAP vaccine schedule ─────────────────────────────────────────────────────
const IAP_SCHEDULE = [
  { name: "BCG",                              weeks: 0   },
  { name: "OPV-0",                            weeks: 0   },
  { name: "HepB-1",                           weeks: 0   },
  { name: "OPV-1",                            weeks: 6   },
  { name: "Pentavalent-1",                    weeks: 6   },
  { name: "PCV-1",                            weeks: 6   },
  { name: "Rota-1",                           weeks: 6   },
  { name: "OPV-2",                            weeks: 10  },
  { name: "Pentavalent-2",                    weeks: 10  },
  { name: "PCV-2",                            weeks: 10  },
  { name: "Rota-2",                           weeks: 10  },
  { name: "OPV-3",                            weeks: 14  },
  { name: "Pentavalent-3",                    weeks: 14  },
  { name: "PCV-3",                            weeks: 14  },
  { name: "Rota-3",                           weeks: 14  },
  { name: "MR-1",                             weeks: 48  },
  { name: "JE-1",                             weeks: 48  },
  { name: "Vitamin A-1",                      weeks: 48  },
  { name: "OPV-4",                            weeks: 48  },
  { name: "MR-2",                             weeks: 96  },
  { name: "JE-2",                             weeks: 96  },
  { name: "DPT-Booster-1",                    weeks: 96  },
  { name: "Vitamin A-2",                      weeks: 96  },
  { name: "OPV-5",                            weeks: 96  },
  { name: "DPT-Booster-2",                    weeks: 208 },
  { name: "Td",                               weeks: 208 },
];

/** Safe type code for a vaccine name (no slashes or spaces) */
function vaccineType(name: string) {
  return `vaccine_${name.replace(/[^a-zA-Z0-9-]/g, "_")}`;
}

// ─── GET — generate today's notifications then return all ────────────────────
export async function GET(request: NextRequest) {
  try {
    const auth = await requireFamily();
    if (!auth.success) return NextResponse.json({ error: auth.error }, { status: auth.status });

    const familyId  = auth.session!.familyId!;
    const { searchParams } = new URL(request.url);
    const childId   = searchParams.get("childId");

    if (!childId) return NextResponse.json({ error: "childId required" }, { status: 400 });

    const istDate  = getISTDate();
    const istHour  = getISTHour();
    const weekSlot = getISTWeekMonday();

    // ── Fetch child info ──────────────────────────────────────────────────────
    const children = await sql`
      SELECT id, name, birth_date FROM children
      WHERE id = ${childId} AND family_id = ${familyId}
    `;
    if (!children[0]) return NextResponse.json({ notifications: [] });
    const child     = children[0];
    const birthDate = new Date(child.birth_date as string);

    // ── 1. Vaccine notifications ──────────────────────────────────────────────
    const given = await sql`
      SELECT vaccine_name FROM vaccinations
      WHERE child_id = ${childId} AND status = 'given'
    `;
    const givenSet = new Set((given as unknown as { vaccine_name: string }[]).map(r => r.vaccine_name));

    const today = new Date(istDate + "T00:00:00Z"); // IST midnight as Date for comparison

    for (const v of IAP_SCHEDULE) {
      if (givenSet.has(v.name)) continue;

      const dueDate    = new Date(birthDate.getTime() + v.weeks * 7 * 86_400_000);
      const dueDateStr = dueDate.toISOString().slice(0, 10);

      // Only notify if due today or overdue
      if (dueDateStr > istDate) continue;

      const diffDays = Math.round((today.getTime() - dueDate.getTime()) / 86_400_000);
      const isToday  = diffDays === 0;

      await sql`
        INSERT INTO notifications
          (family_id, child_id, type, title, message, action_url, scheduled_for, metadata)
        VALUES (
          ${familyId}, ${childId},
          ${vaccineType(v.name)},
          ${isToday ? "Vaccine due today" : "Vaccine overdue"},
          ${isToday
            ? `${v.name} is due today`
            : `${v.name} is ${diffDays} day${diffDays === 1 ? "" : "s"} overdue`},
          '/medical',
          ${dueDateStr}::date,
          ${JSON.stringify({ vaccineName: v.name, dueDate: dueDateStr })}::jsonb
        )
        ON CONFLICT (family_id, child_id, type, scheduled_for) DO UPDATE SET
          title      = EXCLUDED.title,
          message    = EXCLUDED.message,
          action_url = EXCLUDED.action_url,
          metadata   = EXCLUDED.metadata
      `;
    }

    // ── 2. Log nudge — no activity today past noon IST ────────────────────────
    if (istHour >= 12) {
      const logCount = await sql`
        SELECT
          (SELECT COUNT(*) FROM feeds        WHERE child_id = ${childId} AND (logged_at AT TIME ZONE 'Asia/Kolkata')::date = ${istDate}::date) +
          (SELECT COUNT(*) FROM diapers_logs WHERE child_id = ${childId} AND (logged_at AT TIME ZONE 'Asia/Kolkata')::date = ${istDate}::date) +
          (SELECT COUNT(*) FROM sleeps       WHERE child_id = ${childId} AND (logged_at AT TIME ZONE 'Asia/Kolkata')::date = ${istDate}::date)
          AS total
      `;
      if (Number((logCount[0] as { total: string }).total) === 0) {
        await sql`
          INSERT INTO notifications
            (family_id, child_id, type, title, message, action_url, scheduled_for)
          VALUES (
            ${familyId}, ${childId}, 'log_nudge',
            ${'No activity logged yet today'},
            ${`How is ${child.name as string} doing? Log a feed, diaper change, or sleep session`},
            '/activity',
            ${istDate}::date
          )
          ON CONFLICT (family_id, child_id, type, scheduled_for) DO NOTHING
        `;
      }
    }

    // ── 3. Memory nudge — no photo shared today ───────────────────────────────
    const memCount = await sql`
      SELECT COUNT(*) AS total FROM memories
      WHERE family_id = ${familyId}
        AND (created_at AT TIME ZONE 'Asia/Kolkata')::date = ${istDate}::date
    `;
    if (Number((memCount[0] as { total: string }).total) === 0) {
      await sql`
        INSERT INTO notifications
          (family_id, child_id, type, title, message, action_url, scheduled_for)
        VALUES (
          ${familyId}, ${childId}, 'memory_nudge',
          ${'Capture a moment today 📸'},
          ${`Add a photo of ${child.name as string} to your memories — your future self will thank you`},
          '/memories',
          ${istDate}::date
        )
        ON CONFLICT (family_id, child_id, type, scheduled_for) DO NOTHING
      `;
    }

    // ── 4. Garment nudge — wardrobe has fewer than 10 items (weekly) ──────────
    const garmentCount = await sql`
      SELECT COUNT(*) AS total FROM garments
      WHERE child_id = ${childId} AND status = 'active'
    `;
    if (Number((garmentCount[0] as { total: string }).total) < 10) {
      await sql`
        INSERT INTO notifications
          (family_id, child_id, type, title, message, action_url, scheduled_for)
        VALUES (
          ${familyId}, ${childId}, 'garment_nudge',
          ${'Build out the wardrobe 👚'},
          ${`Add clothes to ${child.name as string}'s wardrobe to unlock outfit suggestions`},
          '/wardrobe/add',
          ${weekSlot}::date
        )
        ON CONFLICT (family_id, child_id, type, scheduled_for) DO NOTHING
      `;
    }

    // ── 5. Return all notifications, filtering out given vaccines ─────────────
    const rows = await sql`
      SELECT n.*
      FROM notifications n
      WHERE n.family_id = ${familyId}
        AND n.child_id  = ${childId}
        AND (
          -- Non-vaccine rows: always include
          n.type NOT LIKE 'vaccine_%'
          OR
          -- Vaccine rows: only if the vaccine hasn't been given
          NOT EXISTS (
            SELECT 1 FROM vaccinations v
            WHERE v.child_id    = n.child_id
              AND v.status      = 'given'
              AND v.vaccine_name = n.metadata->>'vaccineName'
          )
        )
      ORDER BY n.is_read ASC, n.created_at DESC
      LIMIT 60
    `;

    return NextResponse.json({
      notifications: (rows as Record<string, unknown>[]).map(r => ({
        id:           r.id,
        type:         r.type,
        title:        r.title,
        message:      r.message,
        actionUrl:    r.action_url,
        isRead:       r.is_read,
        scheduledFor: r.scheduled_for,
        createdAt:    r.created_at,
        metadata:     r.metadata,
      })),
    });
  } catch (err) {
    console.error("Notifications GET error:", err);
    return NextResponse.json({ error: String(err) }, { status: 500 });
  }
}

// ─── PATCH — mark all notifications as read for this family+child ─────────────
export async function PATCH(request: NextRequest) {
  try {
    const auth = await requireFamily();
    if (!auth.success) return NextResponse.json({ error: auth.error }, { status: auth.status });

    const familyId = auth.session!.familyId!;
    const body = await request.json().catch(() => ({})) as { childId?: string };
    const childId  = body.childId;

    if (!childId) return NextResponse.json({ error: "childId required" }, { status: 400 });

    await sql`
      UPDATE notifications
      SET is_read = true
      WHERE family_id = ${familyId} AND child_id = ${childId} AND is_read = false
    `;

    return NextResponse.json({ success: true });
  } catch (err) {
    console.error("Notifications PATCH error:", err);
    return NextResponse.json({ error: String(err) }, { status: 500 });
  }
}
