"use client";

import { useEffect, useMemo, useState } from "react";

import { Badge } from "@/components/dashboard-ui";
import {
  actionItems,
  calendarEvents,
  complianceItems,
  daysUntil,
  formatDate,
  getPropertyName,
  properties,
  residents,
  workOrders,
} from "@/lib/property-data-uk";
import {
  type ReminderCategory,
  type ReminderPreferences,
  defaultReminderPreferences,
  loadReminderPreferences,
  reminderCategoryOptions,
  saveReminderPreferences,
} from "@/lib/reminder-preferences";

type CalendarReminder = {
  id: string;
  title: string;
  description: string;
  date: string;
  category: ReminderCategory;
  propertyName?: string;
};

const leadDayOptions = [1, 3, 7, 14, 30, 60, 90];

function makeReminderId(prefix: string, id: string) {
  return `${prefix}-${id}`.replace(/[^a-z0-9-]/gi, "-").toLowerCase();
}

function nextDay(date: string) {
  const [year = 1970, month = 1, day = 1] = date.split("-").map(Number);
  const next = new Date(Date.UTC(year, month - 1, day + 1));

  return next.toISOString().slice(0, 10);
}

function toIcsDate(date: string) {
  return date.replace(/-/g, "");
}

function toIcsStamp(date: Date) {
  return date.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}/, "");
}

function escapeIcs(value: string) {
  return value
    .replace(/\\/g, "\\\\")
    .replace(/;/g, "\\;")
    .replace(/,/g, "\\,")
    .replace(/\r?\n/g, "\\n");
}

function buildCalendarReminders(): CalendarReminder[] {
  const safetyReminders = complianceItems
    .filter((item) => item.status !== "Completed")
    .map<CalendarReminder>((item) => ({
      id: makeReminderId("safety", item.id),
      title: `${item.title} - ${getPropertyName(item.propertyId)}`,
      description: `${item.type}. Owner: ${item.owner}. Status: ${item.status}.`,
      date: item.dueDate,
      category: "safety",
      propertyName: getPropertyName(item.propertyId),
    }));

  const taskReminders = actionItems.map<CalendarReminder>((item) => ({
    id: makeReminderId("task", item.id),
    title: item.title,
    description: `${item.owner}: ${item.detail}`,
    date: item.dueDate,
    category: "tasks",
  }));

  const diaryReminders = calendarEvents.map<CalendarReminder>((event) => ({
    id: makeReminderId("diary", event.id),
    title: event.title,
    description: `${event.category}. Owner: ${event.owner}.`,
    date: event.date,
    category: "diary",
    propertyName: event.propertyId ? getPropertyName(event.propertyId) : undefined,
  }));

  const repairReminders = workOrders
    .filter(
      (order) =>
        order.status !== "Resolved" &&
        (order.priority === "Critical" || order.priority === "High"),
    )
    .map<CalendarReminder>((order) => ({
      id: makeReminderId("repair", order.id),
      title: `${order.priority} repair: ${order.title}`,
      description: `${order.category}. Assigned to ${order.assignedTo}. Status: ${order.status}.`,
      date: order.createdAt.slice(0, 10),
      category: "repairs",
      propertyName: getPropertyName(order.propertyId),
    }));

  const inspectionReminders = properties.flatMap<CalendarReminder>((property) => [
    {
      id: makeReminderId("inspection", property.id),
      title: `Inspection - ${property.name}`,
      description: `${property.address}, ${property.city}, ${property.postcode}.`,
      date: property.nextInspection,
      category: "inspections",
      propertyName: property.name,
    },
    {
      id: makeReminderId("epc-expiry", property.id),
      title: `EPC expiry - ${property.name}`,
      description: `Current EPC rating ${property.epcRating}.`,
      date: property.epcExpires,
      category: "inspections",
      propertyName: property.name,
    },
  ]);

  const tenancyReminders = residents.map<CalendarReminder>((resident) => ({
    id: makeReminderId("tenancy", resident.id),
    title: `Tenancy touchpoint - ${resident.name}`,
    description: `${resident.unit} at ${getPropertyName(
      resident.propertyId,
    )}. Renewal stage: ${resident.renewalStage}. Deposit: ${resident.depositStatus}.`,
    date: resident.tenancyEnds,
    category: "tenancies",
    propertyName: getPropertyName(resident.propertyId),
  }));

  return [
    ...safetyReminders,
    ...taskReminders,
    ...diaryReminders,
    ...repairReminders,
    ...inspectionReminders,
    ...tenancyReminders,
  ].sort((left, right) => left.date.localeCompare(right.date));
}

function buildIcsCalendar(
  reminders: CalendarReminder[],
  preferences: ReminderPreferences,
) {
  const stamp = toIcsStamp(new Date());
  const leadDays = Math.max(1, preferences.leadDays);
  const lines = [
    "BEGIN:VCALENDAR",
    "VERSION:2.0",
    "CALSCALE:GREGORIAN",
    "METHOD:PUBLISH",
    "PRODID:-//PropertyPilot//UK Property Reminders//EN",
    `X-WR-CALNAME:${escapeIcs(preferences.calendarName)}`,
    "X-WR-TIMEZONE:Europe/London",
    ...reminders.flatMap((reminder) => [
      "BEGIN:VEVENT",
      `UID:${escapeIcs(reminder.id)}@propertypilot.local`,
      `DTSTAMP:${stamp}`,
      `DTSTART;VALUE=DATE:${toIcsDate(reminder.date)}`,
      `DTEND;VALUE=DATE:${toIcsDate(nextDay(reminder.date))}`,
      `SUMMARY:${escapeIcs(reminder.title)}`,
      `DESCRIPTION:${escapeIcs(
        `${reminder.description} ${
          reminder.propertyName ? `Property: ${reminder.propertyName}.` : ""
        } Exported from PropertyPilot.`,
      )}`,
      `CATEGORIES:${escapeIcs(reminder.category)}`,
      "BEGIN:VALARM",
      "ACTION:DISPLAY",
      `DESCRIPTION:${escapeIcs(`PropertyPilot reminder: ${reminder.title}`)}`,
      `TRIGGER:-P${leadDays}D`,
      "END:VALARM",
      "END:VEVENT",
    ]),
    "END:VCALENDAR",
  ];

  return `${lines.join("\r\n")}\r\n`;
}

function downloadCalendarFile(
  reminders: CalendarReminder[],
  preferences: ReminderPreferences,
) {
  const content = buildIcsCalendar(reminders, preferences);
  const blob = new Blob([content], { type: "text/calendar;charset=utf-8" });
  const url = URL.createObjectURL(blob);
  const anchor = window.document.createElement("a");

  anchor.href = url;
  anchor.download = `${preferences.calendarName
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, "-")
    .replace(/^-|-$/g, "") || "propertypilot-reminders"}.ics`;
  anchor.click();
  window.setTimeout(() => URL.revokeObjectURL(url), 1000);
}

export function CalendarReminderSettings() {
  const [preferences, setPreferences] = useState<ReminderPreferences>(
    defaultReminderPreferences,
  );
  const [statusMessage, setStatusMessage] = useState("");
  const [browserPermission, setBrowserPermission] = useState<
    "default" | "denied" | "granted" | "unsupported"
  >("unsupported");
  const reminders = useMemo(() => buildCalendarReminders(), []);
  const activeReminders = reminders.filter(
    (reminder) => preferences.categories[reminder.category],
  );
  const upcomingCount = activeReminders.filter((reminder) => {
    const days = daysUntil(reminder.date);
    return days >= 0 && days <= preferences.leadDays;
  }).length;

  useEffect(() => {
    let active = true;
    const timer = window.setTimeout(() => {
      if (!active) {
        return;
      }

      setPreferences(loadReminderPreferences());

      if ("Notification" in window) {
        setBrowserPermission(Notification.permission);
      }
    }, 0);

    return () => {
      active = false;
      window.clearTimeout(timer);
    };
  }, []);

  function updatePreferences(nextPreferences: ReminderPreferences) {
    setPreferences(nextPreferences);
    saveReminderPreferences(nextPreferences);
    setStatusMessage("Reminder settings saved.");
  }

  function updateCategory(category: ReminderCategory, enabled: boolean) {
    updatePreferences({
      ...preferences,
      categories: {
        ...preferences.categories,
        [category]: enabled,
      },
    });
  }

  async function enableBrowserReminders() {
    if (!("Notification" in window)) {
      setBrowserPermission("unsupported");
      setStatusMessage("This browser does not support desktop reminders.");
      return;
    }

    const permission = await Notification.requestPermission();
    setBrowserPermission(permission);

    if (permission === "granted") {
      setStatusMessage(
        "Browser reminders are enabled while PropertyPilot is open on this device.",
      );
      new Notification("PropertyPilot reminders enabled", {
        body: `You will see in-app reminders ${preferences.leadDays} days before selected deadlines.`,
      });
    } else {
      setStatusMessage("Browser reminders were not enabled.");
    }
  }

  function handleDownload() {
    downloadCalendarFile(activeReminders, preferences);
    setStatusMessage(
      "Calendar file downloaded. Import it into Apple Calendar, Outlook, or Google Calendar.",
    );
  }

  return (
    <div className="space-y-4">
      <div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
        <div>
          <p className="text-sm font-semibold text-foreground">
            Calendar and reminders
          </p>
          <p className="mt-1 text-xs leading-5 text-muted">
            Export PropertyPilot due dates to your own calendar and choose which
            reminders feed the notification bell.
          </p>
        </div>
        <Badge tone={upcomingCount > 0 ? "amber" : "success"}>
          {upcomingCount} within {preferences.leadDays} days
        </Badge>
      </div>

      <div className="grid gap-3 sm:grid-cols-[1fr_0.55fr]">
        <label className="space-y-2 text-xs font-semibold uppercase tracking-[0.18em] text-muted">
          Calendar name
          <input
            value={preferences.calendarName}
            onChange={(event) =>
              updatePreferences({
                ...preferences,
                calendarName: event.currentTarget.value,
              })
            }
            className="w-full rounded-[16px] border border-border bg-surface-strong px-3 py-2.5 text-sm normal-case tracking-normal text-foreground outline-none transition focus:border-primary"
          />
        </label>

        <label className="space-y-2 text-xs font-semibold uppercase tracking-[0.18em] text-muted">
          Remind me before
          <select
            value={preferences.leadDays}
            onChange={(event) =>
              updatePreferences({
                ...preferences,
                leadDays: Number(event.currentTarget.value),
              })
            }
            className="w-full rounded-[16px] border border-border bg-surface-strong px-3 py-2.5 text-sm normal-case tracking-normal text-foreground outline-none transition focus:border-primary"
          >
            {leadDayOptions.map((days) => (
              <option key={days} value={days}>
                {days} {days === 1 ? "day" : "days"}
              </option>
            ))}
          </select>
        </label>
      </div>

      <div className="grid gap-2 sm:grid-cols-2">
        {reminderCategoryOptions.map((option) => (
          <label
            key={option.id}
            className="flex items-start gap-3 rounded-[18px] border border-border bg-surface-strong p-3"
          >
            <input
              checked={preferences.categories[option.id]}
              onChange={(event) => updateCategory(option.id, event.currentTarget.checked)}
              className="mt-1 h-4 w-4 accent-primary"
              type="checkbox"
            />
            <span>
              <span className="block text-sm font-semibold text-foreground">
                {option.label}
              </span>
              <span className="mt-1 block text-xs leading-5 text-muted">
                {option.description}
              </span>
            </span>
          </label>
        ))}
      </div>

      <div className="grid gap-3 sm:grid-cols-2">
        <button
          className="rounded-full border border-primary bg-primary px-4 py-2.5 text-sm font-semibold text-white transition hover:bg-primary/90"
          onClick={handleDownload}
          type="button"
        >
          Download calendar file
        </button>
        <button
          className="rounded-full border border-border bg-white/68 px-4 py-2.5 text-sm font-semibold text-foreground transition hover:border-primary/35 hover:text-primary disabled:cursor-not-allowed disabled:opacity-60"
          disabled={browserPermission === "denied"}
          onClick={enableBrowserReminders}
          type="button"
        >
          {browserPermission === "granted"
            ? "Browser reminders enabled"
            : browserPermission === "denied"
              ? "Browser reminders blocked"
              : "Enable browser reminders"}
        </button>
      </div>

      <div className="rounded-[18px] border border-border bg-surface-strong p-3 text-xs leading-5 text-muted">
        <p className="font-semibold text-foreground">
          How to add it to your calendar
        </p>
        <p className="mt-1">
          Download the `.ics` file, then import it into Apple Calendar, Outlook, or
          Google Calendar. Each item includes an alert {preferences.leadDays} days
          before the due date.
        </p>
      </div>

      {statusMessage ? (
        <p className="rounded-[16px] border border-accent/20 bg-accent-soft px-3 py-2 text-xs leading-5 text-foreground">
          {statusMessage}
        </p>
      ) : null}

      <div className="space-y-2">
        <p className="text-xs font-semibold uppercase tracking-[0.18em] text-muted">
          Next exported reminders
        </p>
        {activeReminders.slice(0, 4).map((reminder) => (
          <div
            key={reminder.id}
            className="flex items-start justify-between gap-3 rounded-[16px] border border-border bg-surface-strong px-3 py-2"
          >
            <div>
              <p className="text-sm font-semibold text-foreground">{reminder.title}</p>
              <p className="mt-1 text-xs text-muted">
                {reminder.propertyName ? `${reminder.propertyName} - ` : ""}
                {formatDate(reminder.date)}
              </p>
            </div>
            <Badge tone={daysUntil(reminder.date) <= preferences.leadDays ? "amber" : "neutral"}>
              {reminder.category}
            </Badge>
          </div>
        ))}
      </div>
    </div>
  );
}
