import { createContext, useContext, useMemo, useState, useCallback, type ReactNode } from 'react';
import { createEffigenixClient, type EffigenixClient, type TokenProvider } from '@effigenix/api-client';
import { fetch as tauriFetch } from '@tauri-apps/plugin-http';

const API_BASE = import.meta.env.VITE_API_URL || 'http://localhost:8080';

/**
 * Axios adapter that delegates to Tauri's HTTP plugin.
 * Bypasses CORS restrictions on mobile webviews.
 */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const tauriAdapter = async (config: any) => {
  const url = new URL(config.url || '', config.baseURL);

  const headers: Record<string, string> = {};
  if (config.headers) {
    const raw = typeof config.headers.toJSON === 'function' ? config.headers.toJSON(false) : config.headers;
    for (const [key, value] of Object.entries(raw)) {
      if (value != null) headers[key] = String(value);
    }
  }

  const response = await tauriFetch(url.toString(), {
    method: (config.method || 'GET').toUpperCase(),
    headers,
    body: config.data != null
      ? (typeof config.data === 'string' ? config.data : JSON.stringify(config.data))
      : undefined,
  });

  let data: unknown;
  const contentType = response.headers.get('content-type') || '';
  if (contentType.includes('application/json')) {
    data = await response.json();
  } else {
    data = await response.text();
  }

  return {
    data,
    status: response.status,
    statusText: response.statusText,
    headers: Object.fromEntries(response.headers.entries()),
    config,
  };
};

interface ApiState {
  client: EffigenixClient;
  login: (username: string, password: string) => Promise<void>;
  isAuthenticated: boolean;
}

const ApiContext = createContext<ApiState | null>(null);

export function ApiProvider({ children }: { children: ReactNode }) {
  const [tokens, setTokens] = useState<{ access: string; refresh: string } | null>(null);

  const tokenProvider = useMemo<TokenProvider>(() => ({
    getAccessToken: async () => tokens?.access ?? null,
    getRefreshToken: async () => tokens?.refresh ?? null,
    saveTokens: async (accessToken, refreshToken) => {
      setTokens({ access: accessToken, refresh: refreshToken });
    },
    clearTokens: async () => setTokens(null),
  }), [tokens]);

  const client = useMemo(() => createEffigenixClient(tokenProvider, {
    baseUrl: API_BASE,
    adapter: tauriAdapter,
  }), [tokenProvider]);

  const login = useCallback(async (username: string, password: string) => {
    const res = await tauriFetch(`${API_BASE}/api/auth/login`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ username, password }),
    });
    if (!res.ok) {
      const text = await res.text();
      throw new Error(`${res.status}: ${text}`);
    }
    const data = await res.json();
    setTokens({ access: data.accessToken, refresh: data.refreshToken });
  }, []);

  return (
    <ApiContext.Provider value={{ client, login, isAuthenticated: tokens !== null }}>
      {children}
    </ApiContext.Provider>
  );
}

export function useApi() {
  const ctx = useContext(ApiContext);
  if (!ctx) throw new Error('useApi must be used within ApiProvider');
  return ctx;
}
