import { redirect } from "react-router";
import { useState } from "react";
import { eq } from "drizzle-orm";
import { Key, Lock, Shield, User } from "lucide-react";
import { auth } from "~/lib/auth.server";
import { database } from "~/database/context";
import * as schema from "~/database/schema";
import {
  findUserById,
  isUserInActiveDraft,
  anonymizeUserAccount,
} from "~/models/user";
import { findTeamsByOwnerId, removeTeamOwner } from "~/models/team";
import { removeAllCommissionersByUserId } from "~/models/commissioner";
import { parseFlagConfig } from "~/lib/flag-types";
import { deleteCloudinaryImageByUrl } from "~/lib/cloudinary.server";
import { sendEmail, wrapInEmailTemplate, emailParagraph } from "~/lib/email.server";
import { logger } from "~/lib/logger";
import {
  SettingsDesktopNav,
  SettingsMobileGridNav,
  SettingsMobileSectionPill,
  type SettingsGridSection,
} from "~/components/league/settings/SettingsNavigation";
import { ProfileSection } from "~/components/user/settings/ProfileSection";
import { AccountSection } from "~/components/user/settings/AccountSection";
import { ApiSection } from "~/components/user/settings/ApiSection";
import { PrivacySection } from "~/components/user/settings/PrivacySection";
import type { Route } from "./+types/settings";

type SectionId = "profile" | "account" | "api" | "privacy";

const SECTIONS: readonly SettingsGridSection[] = [
  { id: "profile", label: "Profile", icon: User, subtitle: "Name, avatar, timezone" },
  { id: "account", label: "Account", icon: Shield, subtitle: "Email, sign-in methods" },
  { id: "api", label: "API Access", icon: Key, subtitle: "Coming soon" },
  { id: "privacy", label: "Data & Privacy", icon: Lock, subtitle: "Export, delete account", isDanger: true },
] as const;

export function meta(): Route.MetaDescriptors {
  return [{ title: "Settings - Brackt" }];
}

export async function loader(args: Route.LoaderArgs) {
  const session = await auth.api.getSession({ headers: args.request.headers });
  if (!session) {
    return redirect("/login?redirectTo=/settings");
  }
  const user = await findUserById(session.user.id);
  if (!user) {
    return redirect("/");
  }
  const isInActiveDraft = await isUserInActiveDraft(session.user.id);

  const db = database();
  const linkedAccounts = await db
    .select({ id: schema.accounts.id, providerId: schema.accounts.providerId })
    .from(schema.accounts)
    .where(eq(schema.accounts.userId, session.user.id));

  return { user, isInActiveDraft, linkedAccounts };
}

export async function action(args: Route.ActionArgs) {
  const session = await auth.api.getSession({ headers: args.request.headers });
  if (!session) {
    return redirect("/login?redirectTo=/settings");
  }

  const user = await findUserById(session.user.id);
  if (!user) {
    return redirect("/");
  }

  const formData = await args.request.formData();
  const intent = formData.get("intent");

  if (intent === "update-avatar-flag") {
    const rawConfig = formData.get("flagConfig");
    if (typeof rawConfig !== "string") {
      return { intent, error: "Flag config is required." };
    }
    let parsedConfig: unknown;
    try {
      parsedConfig = JSON.parse(rawConfig);
    } catch {
      return { intent, error: "Invalid flag config." };
    }
    const flagConfig = parseFlagConfig(parsedConfig);
    if (!flagConfig) {
      return { intent, error: "Invalid flag config." };
    }
    await import("~/models/user").then(({ updateUser }) =>
      updateUser(session.user.id, { flagConfig, avatarType: "flag" })
    );
    return { intent, success: true };
  }

  if (intent === "remove-avatar-photo") {
    await import("~/models/user").then(({ updateUser }) =>
      updateUser(session.user.id, { customAvatarUrl: null, avatarType: "flag" })
    );
    if (user.customAvatarUrl) {
      deleteCloudinaryImageByUrl(user.customAvatarUrl).catch((err) => {
        logger.error("Failed to delete user avatar from Cloudinary:", err);
      });
    }
    return { intent, success: true };
  }

  if (intent === "update-profile") {
    const displayName = formData.get("displayName") as string;
    const username = formData.get("username") as string | null;
    const timezone = formData.get("timezone") as string | null;

    const { TIMEZONE_OPTIONS } = await import("~/components/league/TimezoneSelect");
    const validTimezones = new Set(TIMEZONE_OPTIONS.flatMap((g) => g.zones.map((z) => z.value)));
    const timezoneValue = timezone && validTimezones.has(timezone) ? timezone : undefined;

    await import("~/models/user").then(({ updateUser }) =>
      updateUser(session.user.id, {
        displayName: displayName || undefined,
        username: username || undefined,
        timezone: timezoneValue,
      })
    );
    return { intent, success: true };
  }

  if (intent === "request-data") {
    const notes = (formData.get("dataRequestNotes") as string | null) ?? "";
    const html = wrapInEmailTemplate(`
      ${emailParagraph(`A data export request has been submitted by <strong>${user.email}</strong> (user ID: ${user.id}).`)}
      ${notes ? emailParagraph(`Notes: ${notes}`) : ""}
      ${emailParagraph("Please fulfill this request within 30 days per GDPR/CCPA requirements.")}
    `);
    const { error } = await sendEmail({
      to: "privacy@brackt.com",
      subject: `Data Request from ${user.email}`,
      html,
      replyTo: user.email,
    });
    if (error) {
      logger.error("Failed to send data request email:", error);
      return { intent, dataRequestError: "Failed to submit request. Please email privacy@brackt.com directly." };
    }
    return { intent, dataRequestSuccess: true };
  }

  if (intent === "delete-account") {
    const customAvatarUrl = user.customAvatarUrl;

    const ownedTeams = await findTeamsByOwnerId(session.user.id);
    await Promise.all(ownedTeams.map((team) => removeTeamOwner(team.id)));

    await removeAllCommissionersByUserId(session.user.id);
    await anonymizeUserAccount(session.user.id);

    if (customAvatarUrl) {
      deleteCloudinaryImageByUrl(customAvatarUrl).catch((err) => {
        logger.error("Failed to delete user avatar from Cloudinary after account deletion:", err);
      });
    }

    return redirect("/");
  }

  return { intent, error: "Unknown action." };
}

export default function SettingsPage({ loaderData, actionData }: Route.ComponentProps) {
  const { user, isInActiveDraft, linkedAccounts } = loaderData;
  const [activeSection, setActiveSection] = useState<SectionId>("profile");
  const [mobileView, setMobileView] = useState<"grid" | "section">("grid");

  const handleSectionChange = (id: string, mobile = false) => {
    setActiveSection(id as SectionId);
    if (mobile) setMobileView("section");
  };

  const profileSuccess = actionData?.intent === "update-profile" && "success" in actionData && actionData.success === true;
  const profileError = actionData?.intent === "update-profile" && "error" in actionData ? (actionData as { error: string }).error : undefined;
  const avatarSuccess = (actionData?.intent === "update-avatar-flag" || actionData?.intent === "remove-avatar-photo") && "success" in actionData;
  const dataRequestSuccess = actionData?.intent === "request-data" && "dataRequestSuccess" in actionData ? true : undefined;
  const dataRequestError = actionData?.intent === "request-data" && "dataRequestError" in actionData ? (actionData as { dataRequestError: string }).dataRequestError : undefined;

  return (
    <div className="container mx-auto max-w-5xl px-4 py-6 sm:py-8">
      <div className="mb-6">
        <h1 className="text-2xl font-bold">Settings</h1>
      </div>

      {/* Mobile: grid of sections */}
      {mobileView === "grid" && (
        <div className="lg:hidden">
          <SettingsMobileGridNav
            sections={SECTIONS}
            onSectionChange={(id) => handleSectionChange(id, true)}
          />
        </div>
      )}

      {/* Mobile: back pill when viewing a section */}
      {mobileView === "section" && (
        <SettingsMobileSectionPill onShowGrid={() => setMobileView("grid")} />
      )}

      <div className={`grid gap-6 lg:grid-cols-[220px_minmax(0,1fr)] ${mobileView === "grid" ? "hidden lg:grid" : "grid"}`}>
        <SettingsDesktopNav
          sections={SECTIONS}
          activeSection={activeSection}
          onSectionChange={(id) => handleSectionChange(id)}
        />

        <main className="min-w-0">
          {activeSection === "profile" && (
            <ProfileSection
              user={user}
              isInActiveDraft={isInActiveDraft}
              success={profileSuccess || avatarSuccess}
              error={profileError}
            />
          )}
          {activeSection === "account" && (
            <AccountSection
              email={user.email}
              linkedAccounts={linkedAccounts}
            />
          )}
          {activeSection === "api" && <ApiSection />}
          {activeSection === "privacy" && (
            <PrivacySection
              userEmail={user.email}
              dataRequestSuccess={dataRequestSuccess}
              dataRequestError={dataRequestError}
            />
          )}
        </main>
      </div>
    </div>
  );
}
