"use client";

import { useEffect, useMemo, useState } from "react";
import { signOut, useSession } from "next-auth/react";
import type { DepartmentKey, UserRole } from "@/lib/types";
import { ROLE_LABELS } from "@/lib/utils";

const DEPARTMENT_OPTIONS: Array<{ value: DepartmentKey; label: string }> = [
  { value: "marketing", label: "Marketing" },
  { value: "administracion", label: "Administracion" },
  { value: "capital_humano", label: "Capital Humano" },
  { value: "operaciones", label: "Operaciones" },
  { value: "proyectos", label: "Proyectos" },
];

const ROLE_OPTIONS: Array<{ value: UserRole; label: string }> = [
  { value: "owner", label: ROLE_LABELS.owner },
  { value: "leader", label: ROLE_LABELS.leader },
  { value: "employee", label: ROLE_LABELS.employee },
];

type ToastState = {
  kind: "success" | "error";
  message: string;
};

async function readJsonSafe(response: Response): Promise<Record<string, unknown>> {
  const raw = await response.text();
  if (!raw) {
    return {};
  }

  try {
    return JSON.parse(raw) as Record<string, unknown>;
  } catch {
    return {};
  }
}

export default function AccountSettingsPanel() {
  const { data: session, status, update } = useSession();
  const [name, setName] = useState("");
  const [image, setImage] = useState("");
  const [avatarFile, setAvatarFile] = useState<File | null>(null);
  const [department, setDepartment] = useState<DepartmentKey>("marketing");
  const [departmentRole, setDepartmentRole] = useState("");

  const [currentPassword, setCurrentPassword] = useState("");
  const [newPassword, setNewPassword] = useState("");
  const [confirmPassword, setConfirmPassword] = useState("");

  const [isSavingProfile, setIsSavingProfile] = useState(false);
  const [isSavingPassword, setIsSavingPassword] = useState(false);
  const [isApplyingViewAs, setIsApplyingViewAs] = useState(false);
  const [isClearingViewAs, setIsClearingViewAs] = useState(false);
  const [isCleaningLogs, setIsCleaningLogs] = useState(false);
  const [viewAsRole, setViewAsRole] = useState<UserRole>("owner");
  const [viewAsDepartment, setViewAsDepartment] = useState<DepartmentKey>("marketing");
  const [viewAsDepartmentRole, setViewAsDepartmentRole] = useState("");
  const [profileMessage, setProfileMessage] = useState<string | null>(null);
  const [passwordMessage, setPasswordMessage] = useState<string | null>(null);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const [toast, setToast] = useState<ToastState | null>(null);

  useEffect(() => {
    if (!session?.user) {
      return;
    }

    setName(session.user.name ?? "");
    setImage(session.user.image ?? "");
    setDepartment(session.user.department ?? "marketing");
    setDepartmentRole(session.user.departmentRole ?? "");
    setViewAsRole(session.user.viewAsRole ?? session.user.baseRole ?? session.user.role ?? "employee");
    setViewAsDepartment(session.user.viewAsDepartment ?? session.user.baseDepartment ?? session.user.department ?? "marketing");
    setViewAsDepartmentRole(
      session.user.viewAsDepartmentRole ??
        session.user.baseDepartmentRole ??
        session.user.departmentRole ??
        ""
    );
  }, [session?.user]);

  const roleLabel = useMemo(() => ROLE_LABELS[session?.user?.role ?? "employee"], [session?.user?.role]);
  const baseRoleLabel = useMemo(
    () => ROLE_LABELS[session?.user?.baseRole ?? session?.user?.role ?? "employee"],
    [session?.user?.baseRole, session?.user?.role]
  );
  const canElevate = Boolean(session?.user?.canElevate);
  const isViewingAs = Boolean(session?.user?.isViewingAs);

  const pushToast = (kind: ToastState["kind"], message: string) => {
    setToast({ kind, message });
  };

  useEffect(() => {
    if (!toast) {
      return;
    }

    const timeout = setTimeout(() => {
      setToast(null);
    }, 2800);

    return () => clearTimeout(timeout);
  }, [toast]);

  const avatarLabel = useMemo(() => {
    const trimmed = name.trim();
    if (!trimmed) {
      return "U";
    }

    const words = trimmed.split(/\s+/).filter(Boolean);
    if (words.length === 1) {
      return words[0].slice(0, 2).toUpperCase();
    }

    return `${words[0][0] ?? ""}${words[1][0] ?? ""}`.toUpperCase();
  }, [name]);

  const handleSaveProfile = async () => {
    setProfileMessage(null);
    setPasswordMessage(null);
    setErrorMessage(null);
    setIsSavingProfile(true);

    try {
      let nextImage = image;

      if (avatarFile) {
        const data = new FormData();
        data.set("file", avatarFile);

        const uploadResponse = await fetch("/api/account/avatar", {
          method: "POST",
          body: data,
        });

        const uploadPayload = await readJsonSafe(uploadResponse);
        if (!uploadResponse.ok || typeof uploadPayload.imageUrl !== "string") {
          const fallback = `No se pudo subir la foto de perfil (status ${uploadResponse.status}).`;
          throw new Error(typeof uploadPayload.error === "string" ? uploadPayload.error : fallback);
        }

        nextImage = uploadPayload.imageUrl;
      }

      const response = await fetch("/api/account/profile", {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name,
          image: nextImage,
          department,
          departmentRole,
        }),
      });

      const payload = await readJsonSafe(response);
      if (!response.ok) {
        throw new Error(typeof payload.error === "string" ? payload.error : "No se pudo actualizar tu perfil.");
      }

      setImage(nextImage);
      setAvatarFile(null);
      await update();
      setProfileMessage("Perfil actualizado.");
      pushToast("success", "Perfil guardado correctamente.");
    } catch (error) {
      const message = error instanceof Error ? error.message : "No se pudo actualizar tu perfil.";
      setErrorMessage(message);
      pushToast("error", message);
    } finally {
      setIsSavingProfile(false);
    }
  };

  const handleChangePassword = async () => {
    setProfileMessage(null);
    setPasswordMessage(null);
    setErrorMessage(null);

    if (newPassword.length < 8) {
      setErrorMessage("La nueva contrasena debe tener al menos 8 caracteres.");
      return;
    }

    if (newPassword !== confirmPassword) {
      setErrorMessage("La confirmacion de contrasena no coincide.");
      return;
    }

    setIsSavingPassword(true);

    try {
      const response = await fetch("/api/account/password", {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          currentPassword,
          newPassword,
        }),
      });

      const payload = await readJsonSafe(response);
      if (!response.ok) {
        throw new Error(typeof payload.error === "string" ? payload.error : "No se pudo cambiar la contrasena.");
      }

      setCurrentPassword("");
      setNewPassword("");
      setConfirmPassword("");
      setPasswordMessage("Contrasena actualizada.");
      pushToast("success", "Contrasena actualizada.");
    } catch (error) {
      const message = error instanceof Error ? error.message : "No se pudo cambiar la contrasena.";
      setErrorMessage(message);
      pushToast("error", message);
    } finally {
      setIsSavingPassword(false);
    }
  };

  const handleApplyViewAs = async () => {
    if (!canElevate) {
      return;
    }

    setErrorMessage(null);
    setIsApplyingViewAs(true);

    try {
      await update({
        viewAsRole,
        viewAsDepartment,
        viewAsDepartmentRole: viewAsDepartmentRole.trim() || null,
      });
      pushToast("success", "Vista temporal aplicada.");
    } catch {
      const message = "No se pudo aplicar la vista temporal.";
      setErrorMessage(message);
      pushToast("error", message);
    } finally {
      setIsApplyingViewAs(false);
    }
  };

  const handleResetViewAs = async () => {
    if (!canElevate) {
      return;
    }

    setErrorMessage(null);
    setIsClearingViewAs(true);

    try {
      await update({ clearViewAs: true });
      pushToast("success", "Vista temporal desactivada.");
    } catch {
      const message = "No se pudo desactivar la vista temporal.";
      setErrorMessage(message);
      pushToast("error", message);
    } finally {
      setIsClearingViewAs(false);
    }
  };

  const handleCleanupLogs = async () => {
    if (!canElevate) {
      return;
    }

    const confirmed = window.confirm(
      "Esto borrara logs operativos, tokens, invitaciones y sesiones activas de otros usuarios. Deseas continuar?"
    );
    if (!confirmed) {
      return;
    }

    setErrorMessage(null);
    setIsCleaningLogs(true);

    try {
      const response = await fetch("/api/admin/cleanup", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ target: "logs" }),
      });

      const payload = await readJsonSafe(response);
      if (!response.ok) {
        throw new Error(typeof payload.error === "string" ? payload.error : "No se pudo limpiar los logs.");
      }

      const deleted = payload.deleted as Record<string, unknown> | undefined;
      const deletedTotal = deleted
        ? Object.values(deleted).reduce<number>((sum, value) => (typeof value === "number" ? sum + value : sum), 0)
        : 0;

      pushToast("success", `Limpieza completada. Registros borrados: ${deletedTotal}.`);
    } catch (error) {
      const message = error instanceof Error ? error.message : "No se pudo limpiar los logs.";
      setErrorMessage(message);
      pushToast("error", message);
    } finally {
      setIsCleaningLogs(false);
    }
  };

  if (status === "loading") {
    return <p className="text-body text-benell-text-soft">Cargando configuracion...</p>;
  }

  return (
    <div className="space-y-5">
      <section className="rounded-benell border border-benell-stroke bg-benell-surface p-5 shadow-benell">
        <h2 className="text-h2 font-semibold">Mi cuenta</h2>
        <p className="text-body mt-1 text-benell-text-soft">Actualiza tu perfil, departamento operativo y datos de acceso.</p>

        <div className="mt-4 grid gap-4 md:grid-cols-[120px_1fr]">
          <div className="flex items-center justify-center">
            <div
              className="flex size-24 items-center justify-center rounded-full border border-benell-stroke bg-benell-surface-muted text-lg font-semibold text-benell-text"
              style={
                image.trim()
                  ? {
                      backgroundImage: `url(${image.trim()})`,
                      backgroundPosition: "center",
                      backgroundSize: "cover",
                    }
                  : undefined
              }
            >
              {!image.trim() ? avatarLabel : null}
            </div>
          </div>

          <div className="grid gap-3 md:grid-cols-2">
            <label className="flex flex-col gap-1 text-sm text-benell-text-soft md:col-span-2">
              Nombre
              <input
                value={name}
                onChange={(event) => setName(event.target.value)}
                className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
                placeholder="Nombre completo"
              />
            </label>

            <label className="flex flex-col gap-1 text-sm text-benell-text-soft md:col-span-2">
              Foto de perfil (archivo)
              <input
                type="file"
                accept="image/jpeg,image/png,image/webp"
                onChange={(event) => {
                  const next = event.target.files?.[0] ?? null;
                  setAvatarFile(next);
                }}
                className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
              />
              <span className="text-xs text-benell-text-soft">Formatos: JPG, PNG, WEBP. Maximo 5 MB.</span>
              {avatarFile ? <span className="text-xs text-benell-text-soft">Seleccionado: {avatarFile.name}</span> : null}
              {image.trim() ? (
                <button
                  type="button"
                  onClick={() => {
                    setImage("");
                    setAvatarFile(null);
                  }}
                  className="w-fit rounded-lg border border-benell-stroke bg-white px-3 py-1.5 text-xs font-semibold text-benell-text"
                >
                  Quitar foto actual
                </button>
              ) : null}
            </label>

            <label className="flex flex-col gap-1 text-sm text-benell-text-soft">
              Correo
              <input
                value={session?.user?.email ?? ""}
                disabled
                className="rounded-lg border border-benell-stroke bg-benell-surface-muted px-3 py-2 text-sm text-benell-text-soft"
              />
            </label>

            <label className="flex flex-col gap-1 text-sm text-benell-text-soft">
              Rol de plataforma
              <input
                value={roleLabel}
                disabled
                className="rounded-lg border border-benell-stroke bg-benell-surface-muted px-3 py-2 text-sm text-benell-text-soft"
              />
            </label>

            <label className="flex flex-col gap-1 text-sm text-benell-text-soft">
              Departamento
              <select
                value={department}
                onChange={(event) => setDepartment(event.target.value as DepartmentKey)}
                className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
              >
                {DEPARTMENT_OPTIONS.map((option) => (
                  <option key={option.value} value={option.value}>
                    {option.label}
                  </option>
                ))}
              </select>
            </label>

            <label className="flex flex-col gap-1 text-sm text-benell-text-soft">
              Puesto de departamento
              <input
                value={departmentRole}
                onChange={(event) => setDepartmentRole(event.target.value)}
                className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
                placeholder="Ej: Coordinador de Proyectos"
              />
            </label>
          </div>
        </div>

        <div className="mt-4 flex flex-wrap items-center gap-3">
          <button
            type="button"
            onClick={() => void handleSaveProfile()}
            disabled={isSavingProfile}
            className="rounded-lg bg-benell-brown px-4 py-2 text-sm font-semibold text-white disabled:opacity-60"
          >
            {isSavingProfile ? "Guardando..." : "Guardar perfil"}
          </button>
          {profileMessage ? <p className="text-sm text-benell-green">{profileMessage}</p> : null}
        </div>
      </section>

      {canElevate ? (
        <section className="rounded-benell border border-benell-stroke bg-benell-surface p-5 shadow-benell">
          <h2 className="text-h2 font-semibold">Acceso elevado</h2>
          <p className="text-body mt-1 text-benell-text-soft">
            Modo de prueba para cambiar vista de rol/departamento y validar permisos sin modificar roles reales.
          </p>

          <div className="mt-3 rounded-lg border border-benell-stroke bg-white p-3 text-sm text-benell-text-soft">
            <p>Rol real: {baseRoleLabel}</p>
            <p>Rol activo: {roleLabel}</p>
            {isViewingAs ? <p className="font-semibold text-benell-caramel">Vista temporal activa.</p> : <p>Vista real activa.</p>}
          </div>

          <div className="mt-4 grid gap-3 md:grid-cols-3">
            <label className="flex flex-col gap-1 text-sm text-benell-text-soft">
              Ver como rol
              <select
                value={viewAsRole}
                onChange={(event) => setViewAsRole(event.target.value as UserRole)}
                className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
              >
                {ROLE_OPTIONS.map((option) => (
                  <option key={option.value} value={option.value}>
                    {option.label}
                  </option>
                ))}
              </select>
            </label>

            <label className="flex flex-col gap-1 text-sm text-benell-text-soft">
              Ver en departamento
              <select
                value={viewAsDepartment}
                onChange={(event) => setViewAsDepartment(event.target.value as DepartmentKey)}
                className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
              >
                {DEPARTMENT_OPTIONS.map((option) => (
                  <option key={option.value} value={option.value}>
                    {option.label}
                  </option>
                ))}
              </select>
            </label>

            <label className="flex flex-col gap-1 text-sm text-benell-text-soft">
              Puesto temporal
              <input
                value={viewAsDepartmentRole}
                onChange={(event) => setViewAsDepartmentRole(event.target.value)}
                className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
                placeholder="Ej: Lider temporal"
              />
            </label>
          </div>

          <div className="mt-4 flex flex-wrap items-center gap-3">
            <button
              type="button"
              onClick={() => void handleApplyViewAs()}
              disabled={isApplyingViewAs}
              className="rounded-lg bg-benell-brown px-4 py-2 text-sm font-semibold text-white disabled:opacity-60"
            >
              {isApplyingViewAs ? "Aplicando..." : "Aplicar vista temporal"}
            </button>
            <button
              type="button"
              onClick={() => void handleResetViewAs()}
              disabled={isClearingViewAs}
              className="rounded-lg border border-benell-stroke bg-white px-4 py-2 text-sm font-semibold text-benell-text disabled:opacity-60"
            >
              {isClearingViewAs ? "Restaurando..." : "Volver a mi acceso real"}
            </button>
          </div>

          <div className="mt-5 rounded-lg border border-benell-red/30 bg-benell-red/10 p-4">
            <p className="text-sm font-semibold text-benell-red">Zona de limpieza</p>
            <p className="mt-1 text-sm text-benell-text-soft">
              Borra logs operativos, tokens, invitaciones y sesiones de otros usuarios.
            </p>
            <button
              type="button"
              onClick={() => void handleCleanupLogs()}
              disabled={isCleaningLogs}
              className="mt-3 rounded-lg border border-benell-red/50 bg-white px-4 py-2 text-sm font-semibold text-benell-red disabled:opacity-60"
            >
              {isCleaningLogs ? "Limpiando..." : "Borrar logs y sesiones"}
            </button>
          </div>
        </section>
      ) : null}

      <section className="rounded-benell border border-benell-stroke bg-benell-surface p-5 shadow-benell">
        <h2 className="text-h2 font-semibold">Seguridad</h2>
        <p className="text-body mt-1 text-benell-text-soft">Cambia tu contrasena con tu clave actual.</p>

        <div className="mt-4 grid gap-3 md:grid-cols-3">
          <label className="flex flex-col gap-1 text-sm text-benell-text-soft">
            Contrasena actual
            <input
              type="password"
              value={currentPassword}
              onChange={(event) => setCurrentPassword(event.target.value)}
              className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
            />
          </label>

          <label className="flex flex-col gap-1 text-sm text-benell-text-soft">
            Nueva contrasena
            <input
              type="password"
              value={newPassword}
              onChange={(event) => setNewPassword(event.target.value)}
              className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
            />
          </label>

          <label className="flex flex-col gap-1 text-sm text-benell-text-soft">
            Confirmar nueva contrasena
            <input
              type="password"
              value={confirmPassword}
              onChange={(event) => setConfirmPassword(event.target.value)}
              className="rounded-lg border border-benell-stroke bg-white px-3 py-2 text-sm text-benell-text"
            />
          </label>
        </div>

        <div className="mt-4 flex flex-wrap items-center gap-3">
          <button
            type="button"
            onClick={() => void handleChangePassword()}
            disabled={isSavingPassword}
            className="rounded-lg border border-benell-stroke bg-white px-4 py-2 text-sm font-semibold text-benell-text disabled:opacity-60"
          >
            {isSavingPassword ? "Actualizando..." : "Cambiar contrasena"}
          </button>
          {passwordMessage ? <p className="text-sm text-benell-green">{passwordMessage}</p> : null}
        </div>
      </section>

      <section className="rounded-benell border border-benell-stroke bg-benell-surface p-5 shadow-benell">
        <h2 className="text-h2 font-semibold">Sesion</h2>
        <p className="text-body mt-1 text-benell-text-soft">Cierra sesion de forma segura.</p>
        <button
          type="button"
          onClick={() => signOut({ callbackUrl: "/login" })}
          className="mt-4 rounded-lg border border-benell-red/40 bg-benell-red/10 px-4 py-2 text-sm font-semibold text-benell-red"
        >
          Cerrar sesion
        </button>
      </section>

      {errorMessage ? (
        <section className="rounded-benell border border-benell-red/40 bg-benell-red/10 p-4 text-sm text-benell-red">{errorMessage}</section>
      ) : null}

      {toast ? (
        <div className="fixed right-5 top-5 z-[80] w-[min(92vw,360px)] rounded-xl border border-benell-stroke bg-white px-4 py-3 shadow-benell">
          <p className="text-label uppercase tracking-wide text-benell-text-soft">{toast.kind === "success" ? "Guardado" : "Error"}</p>
          <p className={toast.kind === "success" ? "mt-1 text-sm font-semibold text-benell-green" : "mt-1 text-sm font-semibold text-benell-red"}>
            {toast.message}
          </p>
        </div>
      ) : null}
    </div>
  );
}
