import { useEffect, useMemo, useRef, useState, type FormEvent } from "react";
import { Link } from "react-router-dom";
import { useAuth } from "../auth/AuthContext";
import { PageHeader } from "../components/layout/PageHeader";
import { AccountAvatar, Badge, Button, Card, Input, Select, Textarea } from "../components/ui";
import { useRepos } from "../data/DataContext";
import { useI18n } from "../i18n/I18nContext";
import { fileToMemberAvatarDataUrl } from "../lib/memberAvatar";
import { useFormatApiError } from "../lib/apiErrors";
import { memberRoleSummary } from "../lib/memberRole";
import { checkPasswordPolicy } from "../lib/passwordPolicy";

const TIMEZONES = [
  "Asia/Taipei",
  "Asia/Tokyo",
  "Asia/Shanghai",
  "Asia/Hong_Kong",
  "Asia/Singapore",
  "UTC",
  "America/Los_Angeles",
  "America/New_York",
  "Europe/London",
];

export function ProfilePage() {
  const repos = useRepos();
  const { member, updateProfile } = useAuth();
  const { t, locale } = useI18n();
  const formatApiError = useFormatApiError();
  const fileRef = useRef<HTMLInputElement>(null);

  const [displayName, setDisplayName] = useState("");
  const [email, setEmail] = useState("");
  const [bio, setBio] = useState("");
  const [timezone, setTimezone] = useState("Asia/Taipei");
  const [notifyEmail, setNotifyEmail] = useState(true);
  const [currentPassword, setCurrentPassword] = useState("");
  const [newPassword, setNewPassword] = useState("");
  const [confirmPassword, setConfirmPassword] = useState("");
  const [message, setMessage] = useState("");
  /** 基本資料／頭像的頁首錯誤 */
  const [error, setError] = useState("");
  /** 改密：欄位旁錯誤 */
  const [pwErrors, setPwErrors] = useState<{
    current?: string;
    next?: string;
    confirm?: string;
    form?: string;
  }>({});
  const [basicBusy, setBasicBusy] = useState(false);
  const [pwBusy, setPwBusy] = useState(false);
  const [avatarBusy, setAvatarBusy] = useState(false);
  /**
   * 頭像草稿：選檔先上傳拿 URL，儲存基本資料才綁定。
   * 移除則立刻 PATCH 清除（不必再按儲存）。
   */
  const [avatarUrl, setAvatarUrl] = useState<string | null>(null);

  useEffect(() => {
    if (!member) return;
    setDisplayName(member.display_name || "");
    setEmail(member.email || "");
    setBio(member.bio || "");
    setTimezone(member.timezone || "Asia/Taipei");
    setNotifyEmail(member.notify_email ?? true);
    setAvatarUrl(member.avatar_url?.trim() || null);
  }, [member]);

  async function onSaveBasic(e: FormEvent) {
    e.preventDefault();
    setMessage("");
    setError("");
    setBasicBusy(true);
    try {
      // 走 AuthContext.updateProfile：用回傳 member 更新全域狀態，避免再 me() 時 monc 舊快取把頭像帶回來
      const next = await updateProfile({
        display_name: displayName,
        email,
        bio,
        timezone,
        notify_email: notifyEmail,
        avatar_url: avatarUrl,
      });
      setAvatarUrl(next.avatar_url?.trim() || null);
      if (!next.email_verified) {
        setMessage(t("profile.savedUnverified"));
      } else {
        setMessage(t("profile.saved"));
      }
    } catch (err) {
      setError(formatApiError(err, "profile.saveFail"));
    } finally {
      setBasicBusy(false);
    }
  }

  async function onSavePassword(e: FormEvent) {
    e.preventDefault();
    setMessage("");
    setError("");
    const nextErrs: typeof pwErrors = {};
    if (!currentPassword) {
      nextErrs.current = t("profile.needCurrentPassword");
    }
    if (!newPassword) {
      nextErrs.next = t("profile.needNewPassword");
    } else {
      const policy = checkPasswordPolicy(newPassword);
      if (!policy.ok) {
        nextErrs.next = t(policy.errorKey || "password.policy.hint");
      }
    }
    if (newPassword && newPassword !== confirmPassword) {
      nextErrs.confirm = t("profile.passwordMismatch");
    }
    if (Object.keys(nextErrs).length > 0) {
      setPwErrors(nextErrs);
      return;
    }
    setPwErrors({});
    setPwBusy(true);
    try {
      await updateProfile({
        current_password: currentPassword,
        new_password: newPassword,
      });
      setCurrentPassword("");
      setNewPassword("");
      setConfirmPassword("");
      setPwErrors({});
      setMessage(t("profile.passwordUpdated"));
    } catch (err) {
      const msg = formatApiError(err, "profile.passwordFail");
      const code =
        err && typeof err === "object" && "code" in err
          ? Number((err as { code: number }).code)
          : 0;
      // 目前密碼錯 → 掛在目前密碼欄；政策不符 → 新密碼；其餘掛在表單底部
      if (code === 401010) {
        // 登入語意是「Email 或密碼錯誤」；改密情境改成目前密碼錯
        setPwErrors({ current: t("profile.wrongCurrentPassword") });
      } else if (code === 400003) {
        setPwErrors({ next: msg });
      } else {
        setPwErrors({ form: msg });
      }
    } finally {
      setPwBusy(false);
    }
  }

  async function onPickAvatar(file: File | null) {
    if (!file) return;
    setMessage("");
    setError("");
    setAvatarBusy(true);
    try {
      // 先壓成小圖 data URL，再上傳物件儲存，profile 只存 http(s) URL
      const dataUrl = await fileToMemberAvatarDataUrl(file);
      const uploaded = await repos.auth.uploadImage(dataUrl, "avatar");
      setAvatarUrl(uploaded.url);
    } catch (err) {
      setError(formatApiError(err, "profile.avatarFail"));
    } finally {
      setAvatarBusy(false);
      if (fileRef.current) fileRef.current.value = "";
    }
  }

  async function onClearAvatar() {
    setMessage("");
    setError("");
    const prev = avatarUrl;
    setAvatarUrl(null);
    setAvatarBusy(true);
    try {
      // 立刻寫入：avatar_url:null → live 送 "" → 後端 *string 清除
      const next = await updateProfile({ avatar_url: null });
      setAvatarUrl(next.avatar_url?.trim() || null);
      setMessage(t("profile.avatarCleared"));
    } catch (err) {
      setAvatarUrl(prev);
      setError(formatApiError(err, "profile.saveFail"));
    } finally {
      setAvatarBusy(false);
    }
  }

  const role = useMemo(() => memberRoleSummary(member, t), [member, t]);
  const anyBusy = basicBusy || pwBusy || avatarBusy;
  const dateLocale = locale === "en" ? "en-US" : "zh-TW";

  if (!member) {
    return (
      <>
        <PageHeader title={t("profile.title")} />
        <p className="text-muted">{t("common.loading")}</p>
      </>
    );
  }

  return (
    <>
      <PageHeader title={t("profile.title")} />

      {message ? (
        <p className="hb-banner-ok" role="status">
          {message}
        </p>
      ) : null}
      {error ? (
        <p className="hb-form-error" role="alert">
          {error}
        </p>
      ) : null}

      <div className="hb-stack">
        <Card title={t("profile.accountStatus")}>
          <div className="hb-profile-status">
            <div className="hb-profile-role">
              <div className="hb-profile-role__badge">
                <Badge tone={member.email_verified ? "success" : "warning"}>
                  {member.email_verified
                    ? t("profile.emailVerified")
                    : t("profile.emailUnverified")}
                </Badge>
              </div>
              <div className="hb-profile-role__text">
                <p className="hb-profile-role__title">
                  {member.email_verified
                    ? t("profile.emailVerified")
                    : t("profile.emailUnverified")}
                </p>
                <p className="hb-profile-role__meta">
                  {t("profile.loginEmail", { email: member.email })}
                  {member.email_verified_at
                    ? t("profile.verifiedAt", {
                        time: new Date(
                          Math.floor(member.email_verified_at / 1_000_000),
                        ).toLocaleString(dateLocale),
                      })
                    : ""}
                </p>
                {!member.email_verified ? (
                  <p className="hb-profile-role__action">
                    <Link to="/verify-email">
                      <Button type="button">{t("profile.goVerify")}</Button>
                    </Link>
                  </p>
                ) : null}
              </div>
            </div>
            <div className="hb-profile-role">
              <div className="hb-profile-role__badge">
                <Badge tone={role.isAdmin ? "brand" : "neutral"}>{role.primaryLabel}</Badge>
              </div>
              <div className="hb-profile-role__text">
                <p className="hb-profile-role__title">
                  {role.isAdmin ? t("profile.roleAdmin") : t("profile.roleMember")}
                </p>
                <p className="hb-profile-role__meta">
                  {t("profile.roleTags", {
                    labels: role.labels.join(t("profile.listJoin")),
                  })}
                  {t("profile.tenantUid", {
                    tenant: member.tenant_id,
                    uid: member.uid,
                  })}
                </p>
                <p className="hb-profile-role__meta">{t("profile.roleNote")}</p>
              </div>
            </div>
            {member.invite_code ? (
              <div className="hb-profile-role">
                <div className="hb-profile-role__badge">
                  <Badge tone="brand">{t("profile.inviteBadge")}</Badge>
                </div>
                <div className="hb-profile-role__text">
                  <p className="hb-profile-role__title">
                    <code className="hb-invite-code__inline">{member.invite_code}</code>
                  </p>
                  <p className="hb-profile-role__meta">{t("profile.inviteHint")}</p>
                  <p className="hb-profile-role__action">
                    <Link to="/app/invite">
                      <Button type="button" variant="ghost">
                        {t("profile.gotoInvite")}
                      </Button>
                    </Link>
                  </p>
                </div>
              </div>
            ) : null}
          </div>
        </Card>

        <form className="hb-stack" onSubmit={(e) => void onSaveBasic(e)}>
          <Card title={t("profile.basic")}>
            <div className="hb-stack">
              <div className="hb-profile-avatar">
                <AccountAvatar
                  account={{
                    display_name: displayName || member.display_name,
                    username: member.email,
                    avatar_color: "var(--hb-brand)",
                    avatar_url: avatarUrl,
                  }}
                  size="lg"
                  className="hb-profile-avatar__img"
                />
                <div className="hb-profile-avatar__actions">
                  <input
                    ref={fileRef}
                    type="file"
                    accept="image/jpeg,image/png,image/webp,image/gif"
                    className="hb-sr-only"
                    id="member-avatar-file"
                    disabled={avatarBusy || basicBusy}
                    onChange={(e) => void onPickAvatar(e.target.files?.[0] ?? null)}
                  />
                  <div className="hb-profile-avatar__btns">
                    <Button
                      type="button"
                      disabled={avatarBusy || basicBusy}
                      onClick={() => fileRef.current?.click()}
                    >
                      {avatarBusy ? t("common.loading") : t("profile.avatarUpload")}
                    </Button>
                    {avatarUrl ? (
                      <Button
                        type="button"
                        variant="ghost"
                        disabled={avatarBusy || basicBusy}
                        onClick={() => void onClearAvatar()}
                      >
                        {avatarBusy ? t("common.loading") : t("profile.avatarRemove")}
                      </Button>
                    ) : null}
                  </div>
                  <p className="text-muted hb-profile-avatar__hint">{t("profile.avatarHint")}</p>
                </div>
              </div>

              <Input
                label={t("profile.displayName")}
                name="display_name"
                value={displayName}
                onChange={(e) => setDisplayName(e.target.value)}
                required
                maxLength={40}
                autoComplete="nickname"
              />
              <Input
                label={t("login.email")}
                name="email"
                type="email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                required
                autoComplete="email"
              />
              <Textarea
                label={t("profile.bio")}
                name="bio"
                value={bio}
                onChange={(e) => setBio(e.target.value)}
                rows={3}
                placeholder=""
              />
              <Select
                label={t("profile.timezone")}
                value={timezone}
                onChange={(e) => setTimezone(e.target.value)}
              >
                {TIMEZONES.map((tz) => (
                  <option key={tz} value={tz}>
                    {tz}
                  </option>
                ))}
              </Select>
              <label className="hb-check-row">
                <input
                  type="checkbox"
                  checked={notifyEmail}
                  onChange={(e) => setNotifyEmail(e.target.checked)}
                />
                <span>{t("profile.notifyEmail")}</span>
              </label>

              <div className="hb-wizard-actions">
                <Button type="submit" disabled={anyBusy}>
                  {basicBusy ? t("common.loading") : t("profile.saveBasic")}
                </Button>
              </div>
            </div>
          </Card>
        </form>

        <form className="hb-stack" onSubmit={(e) => void onSavePassword(e)}>
          <Card title={t("profile.password")}>
            <div className="hb-stack">
              <Input
                label={t("profile.currentPassword")}
                name="current_password"
                type="password"
                value={currentPassword}
                onChange={(e) => {
                  setCurrentPassword(e.target.value);
                  if (pwErrors.current) setPwErrors((p) => ({ ...p, current: undefined }));
                }}
                autoComplete="current-password"
                error={pwErrors.current}
              />
              <Input
                label={t("profile.newPassword")}
                name="new_password"
                type="password"
                value={newPassword}
                onChange={(e) => {
                  setNewPassword(e.target.value);
                  if (pwErrors.next) setPwErrors((p) => ({ ...p, next: undefined }));
                }}
                autoComplete="new-password"
                placeholder={t("password.policy.hint")}
                hint={pwErrors.next ? undefined : t("password.policy.hint")}
                error={pwErrors.next}
              />
              <Input
                label={t("profile.confirmPassword")}
                name="confirm_password"
                type="password"
                value={confirmPassword}
                onChange={(e) => {
                  setConfirmPassword(e.target.value);
                  if (pwErrors.confirm) setPwErrors((p) => ({ ...p, confirm: undefined }));
                }}
                autoComplete="new-password"
                error={pwErrors.confirm}
              />
              {pwErrors.form ? (
                <p className="hb-form-error" role="alert" style={{ margin: 0 }}>
                  {pwErrors.form}
                </p>
              ) : null}
              <div className="hb-wizard-actions">
                <Button type="submit" disabled={anyBusy}>
                  {pwBusy ? t("common.loading") : t("profile.updatePassword")}
                </Button>
              </div>
            </div>
          </Card>
        </form>
      </div>
    </>
  );
}
