import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from 'react';
import { stripOAuthParamsFromLocation, toAppPath } from '@dukang/weixin-sdk';
import { isWxAuthorizeEnabled } from '@dukang/shared-types';
import type { PartnerMe, PartnerStaffRole } from '@dukang/shared-types';
import {
  clearAuth,
  ensureSession,
  request,
  saveAuth,
  type PartnerSessionPayload,
  type PartnerSessionProfile,
} from '../lib/api';
import { fetchClientConfig, processPartnerWechatOAuthCallback } from '../lib/wechat-auth';
import { isWechatEnv } from '../lib/weixin';

export type PartnerAccount = PartnerMe & {
  staffRole?: PartnerStaffRole;
};

type PartnerSessionValue = {
  ready: boolean;
  authenticated: boolean;
  account: PartnerAccount | null;
  /** @deprecated 使用 authenticated */
  loggedIn: boolean;
  /** @deprecated 使用 ready */
  loading: boolean;
  applySession: (session: PartnerSessionPayload) => void;
  refresh: () => Promise<PartnerAccount | null>;
  logout: () => void;
};

const PartnerSessionContext = createContext<PartnerSessionValue | null>(null);

function accountFromProfile(profile: PartnerSessionProfile): PartnerAccount {
  return {
    id: profile.id,
    name: profile.name,
    phone: profile.phone,
    companyName: profile.companyName ?? '',
    isPrimary: profile.isPrimary ?? true,
    staffRole: profile.staffRole,
    permissions: profile.permissions,
    primaryAccountId: profile.primaryAccountId,
    primaryPhone: profile.primaryPhone,
    primaryName: profile.primaryName,
    hasWechat: profile.hasWechat,
    wxNickname: profile.wxNickname,
    wxAvatarUrl: profile.wxAvatarUrl,
    managedWarehouseId: profile.managedWarehouseId,
    hasWarehouseAccess: profile.hasWarehouseAccess,
  };
}

export function PartnerSessionProvider({ children }: { children: ReactNode }) {
  const [ready, setReady] = useState(false);
  const [authenticated, setAuthenticated] = useState(false);
  const [account, setAccount] = useState<PartnerAccount | null>(null);

  const applySession = useCallback((session: PartnerSessionPayload) => {
    saveAuth(session);
    setAuthenticated(true);
    if (session.partner) {
      setAccount(accountFromProfile(session.partner));
    }
  }, []);

  const refresh = useCallback(async (): Promise<PartnerAccount | null> => {
    try {
      const result = await ensureSession();
      setAuthenticated(result.authenticated);
      if (!result.authenticated || !result.partner) {
        setAccount(null);
        return null;
      }
      const me = await request<PartnerAccount>('PARTNER_H5', '/partner/me', { silent: true });
      setAccount(me);
      return me;
    } catch {
      setAccount(null);
      setAuthenticated(false);
      return null;
    }
  }, []);

  const logout = useCallback(() => {
    clearAuth();
    setAccount(null);
    setAuthenticated(false);
    window.location.href = toAppPath('/login');
  }, []);

  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const params = new URLSearchParams(window.location.search);
        if (isWechatEnv() && params.get('code')) {
          try {
            const config = await fetchClientConfig();
            if (isWxAuthorizeEnabled(config)) {
              const session = await processPartnerWechatOAuthCallback();
              if (session && !cancelled) {
                applySession(session);
                const me = await request<PartnerAccount>('PARTNER_H5', '/partner/me', { silent: true }).catch(() => null);
                if (me && !cancelled) setAccount(me);
              }
              stripOAuthParamsFromLocation();
            }
          } catch {
            stripOAuthParamsFromLocation();
          }
        }

        const result = await ensureSession();
        if (cancelled) return;
        setAuthenticated(result.authenticated);
        if (result.authenticated) {
          const me = await request<PartnerAccount>('PARTNER_H5', '/partner/me', { silent: true }).catch(() => null);
          if (!cancelled) setAccount(me);
        } else {
          setAccount(null);
        }
      } catch {
        if (!cancelled) {
          clearAuth({ keepProfile: true });
          setAuthenticated(false);
          setAccount(null);
        }
      } finally {
        if (!cancelled) setReady(true);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [applySession]);

  const value = useMemo(
    () => ({
      ready,
      authenticated,
      account,
      loggedIn: authenticated,
      loading: !ready,
      applySession,
      refresh,
      logout,
    }),
    [ready, authenticated, account, applySession, refresh, logout],
  );

  return (
    <PartnerSessionContext.Provider value={value}>
      {children}
    </PartnerSessionContext.Provider>
  );
}

export function usePartnerSession(): PartnerSessionValue {
  const ctx = useContext(PartnerSessionContext);
  if (!ctx) throw new Error('usePartnerSession 必须在 PartnerSessionProvider 内使用');
  return ctx;
}

export type { PartnerSessionProfile };
