import { useCallback, useEffect, useMemo, useState } from 'react'
import { Link, useLocation, useNavigate, useSearchParams } from 'react-router-dom'
import { Alert, Button, Divider, Form, Input, Space, Tabs, Typography, message } from 'antd'
import {
  LockOutlined,
  MailOutlined,
  MobileOutlined,
  SafetyOutlined,
  UserOutlined,
} from '@ant-design/icons'

import { useAuth } from '@/app/providers/auth-context'
import { AuthLayout } from '@/layouts'
import { buildOAuthCallbackReturnTo, sanitizeAuthRedirect, validateOAuthUrl } from '@/lib/auth/oauth'
import { getErrorMessage, isFormValidationError } from '@/lib/errors'
import { getDeviceFingerprint } from '@/lib/device-fingerprint'
import {
  getAuthCapabilities,
  getOAuthAuthorizationUrl,
  loginByEmailCode,
  loginByPassword,
  loginBySmsCode,
  sendEmailCode,
  sendSmsCode,
} from '@/services/auth'
import type { AuthCapabilities, TokenBundle } from '@/types'

const { Paragraph, Text, Title } = Typography

const COUNTDOWN_SECONDS = 60
const DEFAULT_CAPABILITIES: AuthCapabilities = {
  password: true,
  email_activation: false,
  email_code: false,
  sms_code: false,
  password_reset: false,
  admin_bootstrap_required: false,
  oauth_providers: [],
}

type LoginFormValues = {
  username: string
  password: string
}

type EmailCodeFormValues = {
  email: string
  code: string
}

type SmsCodeFormValues = {
  phone: string
  code: string
}

export function LoginPage() {
  const [activeTab, setActiveTab] = useState('password')
  const [loading, setLoading] = useState(false)
  const [oauthLoadingProvider, setOAuthLoadingProvider] = useState<string | null>(null)
  const [emailCountdown, setEmailCountdown] = useState(0)
  const [smsCountdown, setSmsCountdown] = useState(0)
  const [capabilities, setCapabilities] = useState<AuthCapabilities>(DEFAULT_CAPABILITIES)
  const [emailForm] = Form.useForm<EmailCodeFormValues>()
  const [smsForm] = Form.useForm<SmsCodeFormValues>()

  const { onLoginSuccess } = useAuth()
  const navigate = useNavigate()
  const [searchParams] = useSearchParams()
  const location = useLocation()

  const redirect = sanitizeAuthRedirect(
    (location.state as { from?: { pathname: string } } | null)?.from?.pathname ||
      searchParams.get('redirect'),
  )

  useEffect(() => {
    if (emailCountdown <= 0) {
      return
    }

    const timer = window.setTimeout(() => setEmailCountdown((current) => current - 1), 1000)
    return () => window.clearTimeout(timer)
  }, [emailCountdown])

  useEffect(() => {
    if (smsCountdown <= 0) {
      return
    }

    const timer = window.setTimeout(() => setSmsCountdown((current) => current - 1), 1000)
    return () => window.clearTimeout(timer)
  }, [smsCountdown])

  useEffect(() => {
    let cancelled = false

    const loadCapabilities = async () => {
      try {
        const result = await getAuthCapabilities()
        if (!cancelled) {
          setCapabilities(result)
        }
      } catch {
        if (!cancelled) {
          setCapabilities(DEFAULT_CAPABILITIES)
        }
      }
    }

    void loadCapabilities()

    return () => {
      cancelled = true
    }
  }, [])

  useEffect(() => {
    if (activeTab === 'email' && !capabilities.email_code) {
      setActiveTab('password')
      return
    }

    if (activeTab === 'sms' && !capabilities.sms_code) {
      setActiveTab('password')
    }
  }, [activeTab, capabilities.email_code, capabilities.sms_code])

  const handleLoginSuccess = useCallback(async (tokenBundle: TokenBundle) => {
    await onLoginSuccess(tokenBundle)
    message.success('登录成功')
    navigate(redirect, { replace: true })
  }, [navigate, onLoginSuccess, redirect])

  const handleOAuthLogin = useCallback(async (provider: string) => {
    setOAuthLoadingProvider(provider)
    try {
      const result = await getOAuthAuthorizationUrl(
        provider,
        buildOAuthCallbackReturnTo(redirect),
      )
      // 验证 OAuth URL origin 防止开放重定向攻击
      if (!validateOAuthUrl(result.auth_url)) {
        throw new Error('Invalid OAuth authorization URL')
      }
      window.location.assign(result.auth_url)
    } catch (error) {
      message.error(getErrorMessage(error, '启动第三方登录失败'))
      setOAuthLoadingProvider(null)
    }
  }, [redirect])

  const handlePasswordLogin = useCallback(async (values: LoginFormValues) => {
    setLoading(true)
    try {
      const deviceInfo = getDeviceFingerprint()
      const tokenBundle = await loginByPassword({
        username: values.username,
        password: values.password,
        ...deviceInfo,
      })
      await handleLoginSuccess(tokenBundle)
    } catch (error) {
      message.error(getErrorMessage(error, '登录失败，请检查用户名和密码'))
    } finally {
      setLoading(false)
    }
  }, [handleLoginSuccess])

  const handleSendEmailCode = useCallback(async () => {
    try {
      const values = await emailForm.validateFields(['email'])
      setEmailCountdown(COUNTDOWN_SECONDS)
      await sendEmailCode({ email: values.email })
      message.success('验证码已发送到邮箱')
    } catch (error) {
      setEmailCountdown(0)
      if (isFormValidationError(error)) {
        return
      }
      message.error(getErrorMessage(error, '发送验证码失败'))
    }
  }, [emailForm])

  const handleEmailCodeLogin = useCallback(async (values: EmailCodeFormValues) => {
    setLoading(true)
    try {
      const tokenBundle = await loginByEmailCode({
        email: values.email,
        code: values.code,
      })
      await handleLoginSuccess(tokenBundle)
    } catch (error) {
      message.error(getErrorMessage(error, '登录失败，请检查验证码'))
    } finally {
      setLoading(false)
    }
  }, [handleLoginSuccess])

  const handleSendSmsCode = useCallback(async () => {
    try {
      const values = await smsForm.validateFields(['phone'])
      setSmsCountdown(COUNTDOWN_SECONDS)
      await sendSmsCode({ phone: values.phone, purpose: 'login' })
      message.success('验证码已发送到手机')
    } catch (error) {
      setSmsCountdown(0)
      if (isFormValidationError(error)) {
        return
      }
      message.error(getErrorMessage(error, '发送验证码失败'))
    }
  }, [smsForm])

  const handleSmsCodeLogin = useCallback(async (values: SmsCodeFormValues) => {
    setLoading(true)
    try {
      const tokenBundle = await loginBySmsCode({
        phone: values.phone,
        code: values.code,
      })
      await handleLoginSuccess(tokenBundle)
    } catch (error) {
      message.error(getErrorMessage(error, '登录失败，请检查验证码'))
    } finally {
      setLoading(false)
    }
  }, [handleLoginSuccess])

  const tabItems = useMemo(() => {
    const items = [
      {
        key: 'password',
        label: '密码登录',
        children: (
          <Form<LoginFormValues> layout="vertical" onFinish={handlePasswordLogin} autoComplete="off">
            <Form.Item name="username" rules={[{ required: true, message: '请输入用户名' }]}>
              <Input
                prefix={<UserOutlined />}
                placeholder="用户名"
                size="large"
                autoComplete="username"
              />
            </Form.Item>
            <Form.Item name="password" rules={[{ required: true, message: '请输入密码' }]}>
              <Input.Password
                prefix={<LockOutlined />}
                placeholder="密码"
                size="large"
                autoComplete="current-password"
              />
            </Form.Item>
            <Form.Item>
              <Button type="primary" htmlType="submit" size="large" block loading={loading}>
                登录
              </Button>
            </Form.Item>
          </Form>
        ),
      },
    ]

    if (capabilities.email_code) {
      items.push({
        key: 'email',
        label: '邮箱验证码',
        children: (
          <Form<EmailCodeFormValues>
            form={emailForm}
            layout="vertical"
            onFinish={handleEmailCodeLogin}
            autoComplete="off"
          >
            <Form.Item
              name="email"
              rules={[
                { required: true, message: '请输入邮箱' },
                { type: 'email', message: '请输入有效的邮箱地址' },
              ]}
            >
              <Input
                prefix={<MailOutlined />}
                placeholder="邮箱地址"
                size="large"
                autoComplete="email"
              />
            </Form.Item>
            <Form.Item
              name="code"
              rules={[
                { required: true, message: '请输入验证码' },
                { len: 6, message: '验证码为 6 位数字' },
              ]}
            >
              <Space.Compact style={{ width: '100%' }}>
                <Input
                  prefix={<SafetyOutlined />}
                  placeholder="验证码"
                  size="large"
                  maxLength={6}
                  style={{ flex: 1 }}
                />
                <Button
                  size="large"
                  disabled={emailCountdown > 0}
                  onClick={() => void handleSendEmailCode()}
                  style={{ width: 120 }}
                >
                  {emailCountdown > 0 ? `${emailCountdown}s` : '获取验证码'}
                </Button>
              </Space.Compact>
            </Form.Item>
            <Form.Item>
              <Button type="primary" htmlType="submit" size="large" block loading={loading}>
                登录
              </Button>
            </Form.Item>
          </Form>
        ),
      })
    }

    if (capabilities.sms_code) {
      items.push({
        key: 'sms',
        label: '短信验证码',
        children: (
          <Form<SmsCodeFormValues>
            form={smsForm}
            layout="vertical"
            onFinish={handleSmsCodeLogin}
            autoComplete="off"
          >
            <Form.Item
              name="phone"
              rules={[
                { required: true, message: '请输入手机号' },
                { pattern: /^1\d{10}$/, message: '请输入有效的手机号' },
              ]}
            >
              <Input
                prefix={<MobileOutlined />}
                placeholder="手机号"
                size="large"
                autoComplete="tel"
              />
            </Form.Item>
            <Form.Item
              name="code"
              rules={[
                { required: true, message: '请输入验证码' },
                { len: 6, message: '验证码为 6 位数字' },
              ]}
            >
              <Space.Compact style={{ width: '100%' }}>
                <Input
                  prefix={<SafetyOutlined />}
                  placeholder="验证码"
                  size="large"
                  maxLength={6}
                  style={{ flex: 1 }}
                />
                <Button
                  size="large"
                  disabled={smsCountdown > 0}
                  onClick={() => void handleSendSmsCode()}
                  style={{ width: 120 }}
                >
                  {smsCountdown > 0 ? `${smsCountdown}s` : '获取验证码'}
                </Button>
              </Space.Compact>
            </Form.Item>
            <Form.Item>
              <Button type="primary" htmlType="submit" size="large" block loading={loading}>
                登录
              </Button>
            </Form.Item>
          </Form>
        ),
      })
    }

    return items
  }, [
    capabilities.email_code,
    capabilities.sms_code,
    emailCountdown,
    emailForm,
    handleEmailCodeLogin,
    handlePasswordLogin,
    handleSendEmailCode,
    handleSendSmsCode,
    handleSmsCodeLogin,
    loading,
    smsCountdown,
    smsForm,
  ])

  const currentTab = tabItems.find((item) => item.key === activeTab) ?? tabItems[0]
  const oauthProviders = useMemo(() => {
    const providers = Array.isArray(capabilities.oauth_providers) ? capabilities.oauth_providers : []
    return providers
      .filter((provider) => provider.enabled !== false)
      .sort((left, right) => left.name.localeCompare(right.name, 'zh-CN'))
  }, [capabilities.oauth_providers])

  return (
    <AuthLayout>
      <Title level={3} style={{ marginBottom: 8 }}>
        欢迎登录
      </Title>
      <Paragraph type="secondary" style={{ marginBottom: 24 }}>
        请选择可用的登录方式
      </Paragraph>

      {capabilities.admin_bootstrap_required && (
        <Alert
          type="warning"
          showIcon
          message="系统尚未初始化首个管理员账号"
          description="当前版本不提供默认账号。请先通过部署初始化流程或管理员初始化工具创建管理员，再使用登录页进入系统。"
          action={(
            <Link to="/bootstrap-admin">
              <Button size="small" type="primary">
                初始化管理员
              </Button>
            </Link>
          )}
          style={{ marginBottom: 24 }}
        />
      )}

      {tabItems.length > 1 ? (
        <Tabs activeKey={activeTab} onChange={setActiveTab} items={tabItems} centered />
      ) : (
        currentTab.children
      )}

      {oauthProviders.length > 0 && (
        <>
          <Divider plain>第三方登录</Divider>
          <Space direction="vertical" size={12} style={{ width: '100%' }}>
            {oauthProviders.map((provider) => (
              <Button
                key={provider.provider}
                block
                size="large"
                onClick={() => void handleOAuthLogin(provider.provider)}
                loading={oauthLoadingProvider === provider.provider}
              >
                使用 {provider.name} 登录
              </Button>
            ))}
          </Space>
        </>
      )}

      <div style={{ textAlign: 'center', marginTop: 16 }}>
        <Space split={<Text type="secondary">|</Text>}>
          {capabilities.password_reset && (
            <Link to="/forgot-password">
              <Text type="secondary">忘记密码？</Text>
            </Link>
          )}
          {capabilities.email_activation && (
            <Link to="/activate-account">
              <Text type="secondary">重新发送激活邮件</Text>
            </Link>
          )}
          <Link to="/register">
            <Text type="secondary">创建账号</Text>
          </Link>
        </Space>
      </div>
    </AuthLayout>
  )
}
