import { useEffect, useMemo, useRef, useState, type CSSProperties, type ReactNode } from "react";
import { Button, Image, Input, ScrollView, Text, View } from "@tarojs/components";
import Taro from "@tarojs/taro";
import { adminLogin } from "../../api/admin";
import { passwordLogin, pcQrConfirm, pcQrScan, sendSmsCode, smsLogin, wechatMiniSession } from "../../api/auth";
import { getSystemPage, type SystemPage } from "../../api/system";
import { setAdminTokens, setAdminUser } from "../../utils/adminAuth";
import { getSmsCooldownSeconds, recordSmsSent, saveLoginTokens } from "../../utils/auth";
import { navigateAfterAuth, normalizeInternalUrl, saveOnboardingSession } from "../../utils/onboarding";
import { useUserStore } from "../../store/user";
import { haptic } from "../../utils/haptics";
import { useRouter } from "@tarojs/taro";
import loginBackground from "../../assets/login/image-2.jpg";
import xlhLogo from "../../assets/login/xlh-logo.jpg";
import "./index.scss";

type LoginMethod = "sms" | "password";
type LoginPanel = "wechat" | "account" | "staff";
type AccountStep = "account" | "code" | "password";

type DrawerTouchEvent = {
  touches?: Array<{ clientY: number }>;
  changedTouches?: Array<{ clientY: number }>;
  stopPropagation?: () => void;
};

function dragWithResistance(delta: number) {
  if (delta > 0) {
    return Math.min(220, delta < 120 ? delta * 0.78 : 94 + (delta - 120) * 0.36);
  }
  const upward = Math.abs(delta);
  return -Math.min(64, upward < 140 ? upward * 0.32 : 45 + (upward - 140) * 0.12);
}

function BottomDrawer({
  title,
  children,
  onClose,
  className = "",
  maskClassName = ""
}: {
  title: string;
  children: ReactNode;
  onClose: () => void;
  className?: string;
  maskClassName?: string;
}) {
  const [dragY, setDragY] = useState(0);
  const [expanded, setExpanded] = useState(false);
  const [isDragging, setIsDragging] = useState(false);
  const startY = useRef(0);
  const dragging = useRef(false);

  function touchY(event: DrawerTouchEvent) {
    return event.touches?.[0]?.clientY ?? event.changedTouches?.[0]?.clientY ?? 0;
  }

  function startDrag(event: DrawerTouchEvent) {
    event.stopPropagation?.();
    haptic("light");
    dragging.current = true;
    setIsDragging(true);
    startY.current = touchY(event);
  }

  function moveDrag(event: DrawerTouchEvent) {
    if (!dragging.current) return;
    event.stopPropagation?.();
    const delta = touchY(event) - startY.current;
    setDragY(dragWithResistance(delta));
  }

  function endDrag(event: DrawerTouchEvent) {
    if (!dragging.current) return;
    event.stopPropagation?.();
    dragging.current = false;
    setIsDragging(false);
    const delta = touchY(event) - startY.current;
    setDragY(0);
    if (expanded && delta > 64) {
      haptic("light");
      setExpanded(false);
      return;
    }
    if (!expanded && delta > 118) {
      haptic("medium");
      onClose();
      return;
    }
    if (delta < -52) {
      haptic("light");
      setExpanded(true);
    }
  }

  const style: CSSProperties | undefined = dragY ? { transform: `translate3d(0, ${dragY}px, 0)` } : undefined;

  return (
    <View className={`drawer-mask ${maskClassName}`} catchMove onClick={() => { haptic("light"); onClose(); }}>
      <View
        className={`bottom-drawer ${expanded ? "expanded" : ""} ${isDragging ? "dragging" : ""} ${className}`}
        style={style}
        catchMove
        onClick={(event) => event.stopPropagation()}
      >
        <View className="drawer-drag-zone" onTouchStart={startDrag} onTouchMove={moveDrag} onTouchEnd={endDrag} onTouchCancel={endDrag}>
          <View className="drawer-handle" />
          <View className="drawer-head">
            <Text className="drawer-title">{title}</Text>
          </View>
        </View>
        {children}
      </View>
    </View>
  );
}

function isPhoneValid(phone: string) {
  return /^1\d{10}$/.test(phone);
}

function isEmailValid(email: string) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}

function identifierType(value: string) {
  const normalized = value.trim();
  if (normalized.includes("@")) return isEmailValid(normalized) ? "email" : "invalid-email";
  return isPhoneValid(normalized) ? "phone" : "invalid-phone";
}

export default function LoginPage() {
  const router = useRouter();
  const [loginMethod, setLoginMethod] = useState<LoginMethod>("sms");
  const [identifier, setIdentifier] = useState("");
  const [code, setCode] = useState("");
  const [password, setPassword] = useState("");
  const [staffUsername, setStaffUsername] = useState("");
  const [staffPassword, setStaffPassword] = useState("");
  const [submitting, setSubmitting] = useState(false);
  const [sending, setSending] = useState(false);
  const [seconds, setSeconds] = useState(() => getSmsCooldownSeconds());
  const [agreed, setAgreed] = useState(true);
  const [panel, setPanel] = useState<LoginPanel>("wechat");
  const [accountStep, setAccountStep] = useState<AccountStep>("account");
  const [drawerInputFocus, setDrawerInputFocus] = useState(false);
  const [legalDoc, setLegalDoc] = useState<SystemPage | null>(null);
  const [legalLoading, setLegalLoading] = useState(false);
  const [legalError, setLegalError] = useState("");
  const bootstrap = useUserStore((state) => state.bootstrap);
  const pcLoginId = useMemo(() => {
    const raw = String(router.params.scene || router.params.loginId || "");
    return raw ? decodeURIComponent(raw) : "";
  }, [router.params.loginId, router.params.scene]);
  const redirectPath = useMemo(() => normalizeInternalUrl(router.params.redirect), [router.params.redirect]);

  useEffect(() => {
    if (!pcLoginId && router.params.staff === "1") {
      setPanel("staff");
    }
  }, [pcLoginId, router.params.staff]);

  useEffect(() => {
    if (seconds <= 0) return;
    const timer = setInterval(() => {
      setSeconds((s) => (s <= 1 ? 0 : s - 1));
    }, 1000);
    return () => clearInterval(timer);
  }, [seconds]);

  useEffect(() => {
    if (!pcLoginId) return;
    void pcQrScan(pcLoginId).catch(() => undefined);
  }, [pcLoginId]);

  useEffect(() => {
    if (panel !== "account" && panel !== "staff") {
      setDrawerInputFocus(false);
      return;
    }
    setDrawerInputFocus(false);
    const timer = setTimeout(() => setDrawerInputFocus(true), 260);
    return () => clearTimeout(timer);
  }, [panel, loginMethod, accountStep]);

  const canSubmit = useMemo(() => {
    if (!agreed || submitting) return false;
    if (loginMethod === "sms") return isPhoneValid(identifier.trim()) && code.trim().length >= 4;
    const type = identifierType(identifier);
    return (type === "phone" || type === "email") && password.trim().length >= 6;
  }, [identifier, code, password, agreed, submitting, loginMethod]);

  const canSendAccountCode = useMemo(() => {
    return isPhoneValid(identifier.trim()) && seconds <= 0 && !sending;
  }, [identifier, seconds, sending]);

  const canGoPasswordNext = useMemo(() => {
    const type = identifierType(identifier);
    return type === "phone" || type === "email";
  }, [identifier]);

  const canStaffSubmit = useMemo(() => {
    return agreed && staffUsername.trim().length >= 3 && staffPassword.trim().length >= 6 && !submitting;
  }, [agreed, staffPassword, staffUsername, submitting]);

  const onSendCode = async () => {
    haptic("light");
    if (!agreed) {
      Taro.showToast({ title: "请先阅读并同意协议", icon: "none" });
      return;
    }
    const phone = identifier.trim();
    if (!isPhoneValid(phone)) {
      Taro.showToast({ title: "请输入正确手机号", icon: "none" });
      return;
    }
    if (seconds > 0 || sending) return;
    setSending(true);
    try {
      await sendSmsCode(phone);
      recordSmsSent();
      setSeconds(60);
      setAccountStep("code");
      Taro.showToast({ title: "验证码已发送", icon: "none" });
    } finally {
      setSending(false);
    }
  };

  const onPasswordNext = () => {
    haptic("light");
    if (!agreed) {
      Taro.showToast({ title: "请先阅读并同意协议", icon: "none" });
      return;
    }
    const type = identifierType(identifier);
    if (type === "invalid-email") {
      Taro.showToast({ title: "请输入正确邮箱地址", icon: "none" });
      return;
    }
    if (type === "invalid-phone") {
      Taro.showToast({ title: "请输入正确手机号或邮箱", icon: "none" });
      return;
    }
    setAccountStep("password");
  };

  const onSubmit = async () => {
    haptic("light");
    if (!canSubmit) return;
    setSubmitting(true);
    try {
      const account = identifier.trim();
      const result = loginMethod === "sms"
        ? await smsLogin(account, code)
        : await passwordLogin(account, password);
      await handleLoginResult(result);
    } finally {
      setSubmitting(false);
    }
  };

  const handleLoginResult = async (result: any) => {
    if (result?.state === "needs_onboarding") {
      if (!result.onboardingToken) {
        Taro.showToast({ title: "账号资料未补全，请使用微信授权继续", icon: "none" });
        return;
      }
      saveOnboardingSession(result.onboardingToken, pcLoginId);
      Taro.showToast({ title: "请继续完善注册信息", icon: "none" });
      await Taro.navigateTo({ url: "/pages/onboarding/index" });
      return;
    }

    const accessToken = result?.accessToken || result?.token;
    if (!accessToken || !result?.refreshToken) {
      Taro.showToast({ title: "登录状态异常，请重新登录", icon: "none" });
      return;
    }

    const accountType = result?.accountType || result?.user?.type;
    if (accountType === "admin") {
      Taro.showModal({
        title: "请走员工通道",
        content: "管理员账号请在登录页底部点击员工通道进入。",
        showCancel: false,
      });
      return;
    }

    saveLoginTokens({ accessToken, refreshToken: result.refreshToken });
    await bootstrap();
    Taro.showToast({
      title: "登录成功",
      icon: "none"
    });
    await navigateAfterAuth(redirectPath, "/pages/home/index");
  };

  const onWechatLogin = async () => {
    haptic("light");
    if (!agreed || submitting) {
      Taro.showToast({ title: "请先阅读并同意协议", icon: "none" });
      return;
    }
    setSubmitting(true);
    try {
      const loginResult = await Taro.login();
      if (!loginResult.code) {
        Taro.showToast({ title: "微信登录失败，请重试", icon: "none" });
        return;
      }
      const result = pcLoginId
        ? await pcQrConfirm(pcLoginId, loginResult.code)
        : await wechatMiniSession(loginResult.code);
      if (result.state === "wechat_unconfigured") {
        Taro.showToast({ title: result.message || "微信登录暂未配置", icon: "none" });
        return;
      }
      if (result.state === "needs_onboarding") {
        if (!result.onboardingToken) {
          Taro.showToast({ title: "账号资料未补全，请重新微信授权", icon: "none" });
          return;
        }
        saveOnboardingSession(result.onboardingToken, pcLoginId);
        Taro.showToast({ title: "请继续完善注册信息", icon: "none" });
        await Taro.navigateTo({ url: "/pages/onboarding/index" });
        return;
      }
      await handleLoginResult(result);
    } finally {
      setSubmitting(false);
    }
  };

  const onStaffLogin = async () => {
    haptic("light");
    if (!agreed) {
      Taro.showToast({ title: "请先阅读并同意协议", icon: "none" });
      return;
    }
    if (!canStaffSubmit) return;
    setSubmitting(true);
    try {
      const result = await adminLogin(staffUsername.trim(), staffPassword);
      setAdminTokens(result.token, result.refreshToken);
      setAdminUser(result.user);
      useUserStore.setState({ adminUser: result.user });
      Taro.showToast({ title: "登录成功", icon: "none" });
      setPanel("wechat");
      setStaffPassword("");
      setTimeout(() => {
        Taro.redirectTo({ url: "/pages/admin-activity-checkin/index" });
      }, 300);
    } finally {
      setSubmitting(false);
    }
  };

  const openLegalDoc = async (code: "agreement" | "privacy") => {
    haptic("light");
    setLegalDoc({ code, title: code === "agreement" ? "用户协议" : "隐私政策", content: "" });
    setLegalLoading(true);
    setLegalError("");
    try {
      setLegalDoc(await getSystemPage(code));
    } catch (error) {
      setLegalError(error instanceof Error ? error.message : "文档加载失败");
    } finally {
      setLegalLoading(false);
    }
  };

  const legalContent = (legalDoc?.content || "")
    .split(/\r?\n/)
    .map((line) => line.trim())
    .filter(Boolean);

  return (
    <View className="login-page">
      <Image className="login-page__background" src={loginBackground} mode="aspectFill" />
      <View className="login-page__content">
        <View className="login-page__brand-block">
          <View className="login-page__logo-card">
            <Image className="login-page__logo" src={xlhLogo} mode="aspectFit" />
          </View>
          <View className="login-page__brand-copy">
            <Text className="login-page__brand">大连市新联会</Text>
            <Text className="login-page__subtitle">e连心</Text>
            <Text className="login-page__intro-line">会员服务、活动报名、建言献策一站式入口</Text>
          </View>
        </View>

        <View className="login-page__panel">
          {pcLoginId ? <Text className="login-page__pc-note">确认电脑端登录</Text> : null}

          <Button className="login-page__wechat-button" loading={submitting} disabled={!agreed || submitting} onClick={onWechatLogin}>
            {pcLoginId ? "确认登录电脑端" : submitting ? "微信授权中..." : "微信授权登录"}
          </Button>

          {!pcLoginId ? (
            <View
              className={agreed ? "login-page__other-entry" : "login-page__other-entry disabled"}
              onClick={() => {
                haptic("light");
                if (!agreed) {
                  Taro.showToast({ title: "请先阅读并同意协议", icon: "none" });
                  return;
                }
                setPanel("account");
                setAccountStep("account");
                setLoginMethod("sms");
                setCode("");
                setPassword("");
              }}
            >
              <Text>其他方式登录</Text>
            </View>
          ) : null}

          <View className="login-agreement auth-agreement" onClick={() => { haptic("light"); setAgreed((v) => !v); }}>
            <View className={agreed ? "agree-box checked" : "agree-box"}>
              {agreed ? <Text>✓</Text> : null}
            </View>
            <View className="agree-text">
              <Text>我已阅读并同意</Text>
              <Text className="agree-link" onClick={(event) => { event.stopPropagation(); void openLegalDoc("agreement"); }}>《用户协议》</Text>
              <Text className="agree-link" onClick={(event) => { event.stopPropagation(); void openLegalDoc("privacy"); }}>《隐私政策》</Text>
            </View>
          </View>

          {!pcLoginId ? (
            <View
              className={agreed ? "login-page__staff-entry" : "login-page__staff-entry disabled"}
              onClick={() => {
                haptic("light");
                if (!agreed) {
                  Taro.showToast({ title: "请先阅读并同意协议", icon: "none" });
                  return;
                }
                setPanel("staff");
              }}
            >
              <Text>员工通道</Text>
            </View>
          ) : null}
        </View>
      </View>
      {!pcLoginId && panel === "account" ? (
        <BottomDrawer
          title={loginMethod === "password" ? "密码登录" : "手机号登录"}
          onClose={() => { haptic("light"); setPanel("wechat"); }}
          className="phone-login-drawer"
        >
          <View className="phone-login-drawer-body">
            {loginMethod === "sms" ? (
              <>
                {accountStep === "code" ? <Text className="phone-login-drawer-copy">验证码已发送至 {identifier.trim()}</Text> : null}
                <View className={accountStep === "code" ? "phone-login-step-viewport with-meta" : "phone-login-step-viewport"}>
                  <View className={accountStep === "code" ? "phone-login-step-track code" : "phone-login-step-track"}>
                    <View className="phone-login-step-panel">
                      <View className="drawer-auth-field drawer-auth-field--plain">
                        <Input
                          className="drawer-auth-input"
                          focus={drawerInputFocus && loginMethod === "sms" && accountStep === "account"}
                          type="number"
                          maxlength={11}
                          cursorSpacing={24}
                          adjustPosition={false}
                          value={identifier}
                          placeholder="请输入手机号"
                          onInput={(e) => setIdentifier(e.detail.value)}
                        />
                      </View>
                    </View>
                    <View className="phone-login-step-panel">
                      <View className="drawer-auth-field drawer-auth-field--plain">
                        <Input
                          className="drawer-auth-input"
                          focus={drawerInputFocus && loginMethod === "sms" && accountStep === "code"}
                          value={code}
                          type="number"
                          maxlength={6}
                          cursorSpacing={24}
                          adjustPosition={false}
                          placeholder="请输入验证码"
                          onInput={(e) => setCode(e.detail.value)}
                        />
                        <Text className="drawer-auth-change" onClick={() => { haptic("light"); setAccountStep("account"); }}>更换手机号</Text>
                      </View>
                    </View>
                  </View>
                </View>
                <View
                  className={accountStep === "code"
                    ? canSubmit ? "drawer-auth-primary" : "drawer-auth-primary translucent"
                    : canSendAccountCode ? "drawer-auth-primary" : "drawer-auth-primary translucent"}
                  onClick={() => accountStep === "code" ? void onSubmit() : void onSendCode()}
                >
                  <Text>{accountStep === "code" ? submitting ? "登录中..." : "登录" : sending ? "发送中..." : seconds > 0 ? `${seconds}s` : "发送验证码"}</Text>
                </View>
                <Text className="drawer-auth-alt" onClick={() => { haptic("light"); setLoginMethod("password"); setAccountStep("account"); setCode(""); }}>密码登录</Text>
              </>
            ) : (
              <>
                <View className={accountStep === "password" ? "phone-login-step-viewport with-meta" : "phone-login-step-viewport"}>
                  <View className={accountStep === "password" ? "phone-login-step-track password" : "phone-login-step-track"}>
                    <View className="phone-login-step-panel">
                      <View className="drawer-auth-field drawer-auth-field--plain">
                        <Input
                          className="drawer-auth-input"
                          focus={drawerInputFocus && loginMethod === "password" && accountStep === "account"}
                          value={identifier}
                          type="text"
                          maxlength={40}
                          cursorSpacing={24}
                          adjustPosition={false}
                          placeholder="请输入手机号或邮箱"
                          onInput={(e) => setIdentifier(e.detail.value)}
                        />
                      </View>
                    </View>
                    <View className="phone-login-step-panel">
                      <View className="drawer-auth-field drawer-auth-field--plain">
                        <Input
                          className="drawer-auth-input"
                          focus={drawerInputFocus && loginMethod === "password" && accountStep === "password"}
                          value={password}
                          password
                          maxlength={32}
                          cursorSpacing={24}
                          adjustPosition={false}
                          placeholder="请输入密码"
                          onInput={(e) => setPassword(e.detail.value)}
                        />
                        <Text className="drawer-auth-change" onClick={() => { haptic("light"); setAccountStep("account"); }}>更换账号</Text>
                      </View>
                    </View>
                  </View>
                </View>
                <View
                  className={accountStep === "password"
                    ? canSubmit ? "drawer-auth-primary" : "drawer-auth-primary translucent"
                    : canGoPasswordNext ? "drawer-auth-primary" : "drawer-auth-primary translucent"}
                  onClick={() => accountStep === "password" ? void onSubmit() : onPasswordNext()}
                >
                  <Text>{accountStep === "password" ? submitting ? "登录中..." : "登录" : "下一步"}</Text>
                </View>
                <Text className="drawer-auth-alt" onClick={() => { haptic("light"); setLoginMethod("sms"); setAccountStep("account"); setPassword(""); }}>验证码登录</Text>
              </>
            )}
          </View>
        </BottomDrawer>
      ) : null}
      {!pcLoginId && panel === "staff" ? (
        <BottomDrawer
          title="员工通道"
          onClose={() => { haptic("light"); setPanel("wechat"); }}
          className="phone-login-drawer staff-login-drawer"
        >
          <View className="phone-login-drawer-body staff-login-drawer-body">
            <Text className="phone-login-drawer-copy">使用管理员账号进入现场签到和补录签到。</Text>
            <View className="drawer-auth-field drawer-auth-field--plain staff-login-field">
              <Input
                className="drawer-auth-input"
                focus={drawerInputFocus && panel === "staff"}
                value={staffUsername}
                type="text"
                maxlength={40}
                cursorSpacing={24}
                adjustPosition={false}
                placeholder="请输入管理员账号"
                onInput={(e) => setStaffUsername(e.detail.value)}
              />
            </View>
            <View className="drawer-auth-field drawer-auth-field--plain staff-login-field">
              <Input
                className="drawer-auth-input"
                value={staffPassword}
                password
                maxlength={32}
                cursorSpacing={24}
                adjustPosition={false}
                placeholder="请输入密码"
                onInput={(e) => setStaffPassword(e.detail.value)}
              />
            </View>
            <View
              className={canStaffSubmit ? "drawer-auth-primary staff-login-submit" : "drawer-auth-primary staff-login-submit translucent"}
              onClick={() => void onStaffLogin()}
            >
              <Text>{submitting ? "登录中..." : "进入员工通道"}</Text>
            </View>
          </View>
        </BottomDrawer>
      ) : null}
      {legalDoc ? (
        <BottomDrawer
          title={legalDoc.title}
          onClose={() => { haptic("light"); setLegalDoc(null); }}
          className="agreement-drawer legal-drawer"
          maskClassName="legal-drawer-mask"
        >
          <ScrollView scrollY className="agreement-scroll legal-drawer__body">
            {legalLoading ? <Text className="legal-drawer__muted">加载中...</Text> : null}
            {legalError ? <Text className="legal-drawer__error">{legalError}</Text> : null}
            {!legalLoading && !legalError && legalContent.length === 0 ? <Text className="legal-drawer__muted">暂无内容</Text> : null}
            {!legalLoading && !legalError ? legalContent.map((line, index) => {
              const isHeading = line.startsWith("#");
              const text = line.replace(/^#{1,3}\s*/, "");
              return (
                <Text key={`${text}-${index}`} className={isHeading ? "legal-drawer__section-title" : "legal-drawer__paragraph"}>
                  {text}
                </Text>
              );
            }) : null}
          </ScrollView>
        </BottomDrawer>
      ) : null}
    </View>
  );
}
