import AsyncStorage from '@react-native-async-storage/async-storage';

const TOKEN_KEY = 'clinic_token';
const PORTAL_KEY = 'clinic_login_portal';
const NAME_KEY = 'clinic_user_name';
const PERMISSIONS_KEY = 'clinic_user_permissions';
const ROLES_KEY = 'clinic_user_roles';
const ACCOUNT_FEATURES_KEY = 'clinic_account_features';
const PLATFORM_FEATURES_KEY = 'clinic_platform_features';
const SUBSCRIPTION_RESTRICTED_KEY = 'clinic_subscription_restricted';
const ACCOUNT_BILLING_KEY = 'clinic_account_billing';

let memoryToken = '';

export function extractLoginToken(data: unknown): string | null {
  if (!data || typeof data !== 'object') return null;
  const record = data as Record<string, unknown>;
  const candidates = [
    record.token,
    record.access_token,
    record.plainTextToken,
    record.data && typeof record.data === 'object'
      ? (record.data as Record<string, unknown>).token
      : null,
  ];
  for (const candidate of candidates) {
    if (typeof candidate === 'string' && candidate.trim()) return candidate.trim();
  }
  return null;
}

export async function initAuthFromStorage(): Promise<void> {
  memoryToken = (await AsyncStorage.getItem(TOKEN_KEY)) || '';
}

export function getAuthToken(): string {
  return memoryToken;
}

export async function saveAuthSession({
  token,
  user,
  portal,
}: {
  token?: string;
  user?: { name?: string; role?: string; permissions?: string[] };
  portal?: string;
}): Promise<void> {
  if (token) {
    memoryToken = token.trim();
    await AsyncStorage.setItem(TOKEN_KEY, memoryToken);
  }
  if (portal) {
    await AsyncStorage.setItem(PORTAL_KEY, portal);
  } else if (user?.role) {
    await AsyncStorage.setItem(PORTAL_KEY, user.role);
  }
  if (user?.name) await AsyncStorage.setItem(NAME_KEY, user.name);
  if (Array.isArray(user?.permissions)) {
    await AsyncStorage.setItem(PERMISSIONS_KEY, JSON.stringify(user.permissions));
  }
}

export async function saveSessionFromMe(payload: {
  user?: {
    name?: string;
    role?: string;
    permissions?: string[];
    account?: {
      status?: string;
      trial_ends_at?: string | null;
      subscription_ends_at?: string | null;
    };
  };
  portal?: string;
  permissions?: string[];
  roles?: string[];
  account_features?: Record<string, boolean>;
  platform_features?: Record<string, boolean>;
  subscription_restricted?: boolean;
}): Promise<void> {
  if (payload?.user) {
    await saveAuthSession({
      token: getAuthToken(),
      user: payload.user,
      portal: payload.portal,
    });
  }
  if (payload?.portal) await AsyncStorage.setItem(PORTAL_KEY, payload.portal);
  if (Array.isArray(payload?.permissions)) {
    await AsyncStorage.setItem(PERMISSIONS_KEY, JSON.stringify(payload.permissions));
  }
  if (Array.isArray(payload?.roles)) {
    await AsyncStorage.setItem(ROLES_KEY, JSON.stringify(payload.roles));
  }
  if (payload?.account_features) {
    await AsyncStorage.setItem(ACCOUNT_FEATURES_KEY, JSON.stringify(payload.account_features));
  }
  if (payload?.platform_features) {
    await AsyncStorage.setItem(PLATFORM_FEATURES_KEY, JSON.stringify(payload.platform_features));
  }
  if (typeof payload?.subscription_restricted === 'boolean') {
    await setAuthSubscriptionRestricted(payload.subscription_restricted);
  }
  const account = payload?.user?.account;
  if (account && typeof account === 'object') {
    await AsyncStorage.setItem(
      ACCOUNT_BILLING_KEY,
      JSON.stringify({
        status: account.status,
        trial_ends_at: account.trial_ends_at,
        subscription_ends_at: account.subscription_ends_at,
      }),
    );
  }
}

export async function persistLoginSession(
  data: Record<string, unknown>,
  fallbackPortal = 'owner',
): Promise<string | null> {
  const token = extractLoginToken(data);
  if (!token) return null;
  const portal = (data.portal as string) || fallbackPortal;
  const user = (data.user as {
    name?: string;
    role?: string;
    permissions?: string[];
    account?: { status?: string; trial_ends_at?: string | null; subscription_ends_at?: string | null };
  }) || undefined;
  await saveAuthSession({ token, user, portal });
  await saveSessionFromMe({
    user,
    portal,
    permissions: data.permissions as string[] | undefined,
    roles: data.roles as string[] | undefined,
    account_features: data.account_features as Record<string, boolean> | undefined,
    platform_features: data.platform_features as Record<string, boolean> | undefined,
    subscription_restricted: data.subscription_restricted as boolean | undefined,
  });
  return token;
}

export async function clearAuthSession(): Promise<void> {
  memoryToken = '';
  const keys = [
    TOKEN_KEY,
    PORTAL_KEY,
    NAME_KEY,
    PERMISSIONS_KEY,
    ROLES_KEY,
    ACCOUNT_FEATURES_KEY,
    PLATFORM_FEATURES_KEY,
    SUBSCRIPTION_RESTRICTED_KEY,
    ACCOUNT_BILLING_KEY,
  ];
  await Promise.all(keys.map((k) => AsyncStorage.removeItem(k)));
}

export async function setAuthSubscriptionRestricted(restricted: boolean): Promise<void> {
  await AsyncStorage.setItem(SUBSCRIPTION_RESTRICTED_KEY, restricted ? '1' : '0');
}

export async function getAuthSubscriptionRestricted(): Promise<boolean> {
  return (await AsyncStorage.getItem(SUBSCRIPTION_RESTRICTED_KEY)) === '1';
}

export async function getAuthAccountBilling(): Promise<{
  status?: string;
  trial_ends_at?: string | null;
  subscription_ends_at?: string | null;
} | null> {
  try {
    const raw = await AsyncStorage.getItem(ACCOUNT_BILLING_KEY);
    return raw ? JSON.parse(raw) : null;
  } catch {
    return null;
  }
}

export async function getAuthLoginPortal(): Promise<string> {
  return (await AsyncStorage.getItem(PORTAL_KEY)) || '';
}

export async function getAuthUserName(): Promise<string> {
  return (await AsyncStorage.getItem(NAME_KEY)) || 'User';
}

export async function getAuthPermissions(): Promise<string[]> {
  try {
    const raw = await AsyncStorage.getItem(PERMISSIONS_KEY);
    return raw ? JSON.parse(raw) : [];
  } catch {
    return [];
  }
}

export async function getAuthUserRoles(): Promise<string[]> {
  try {
    const raw = await AsyncStorage.getItem(ROLES_KEY);
    return raw ? JSON.parse(raw) : [];
  } catch {
    return [];
  }
}

export async function getAuthAccountFeatures(): Promise<Record<string, boolean>> {
  try {
    const raw = await AsyncStorage.getItem(ACCOUNT_FEATURES_KEY);
    return raw ? JSON.parse(raw) : {};
  } catch {
    return {};
  }
}

export async function getAuthPlatformFeatures(): Promise<Record<string, boolean>> {
  try {
    const raw = await AsyncStorage.getItem(PLATFORM_FEATURES_KEY);
    return raw ? JSON.parse(raw) : {};
  } catch {
    return {};
  }
}
