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

const GITEA_BASE_URL = 'https://gitea.techmos.org';
const GITEA_OWNER = 'tech08mag';
const GITEA_REPO = 'carry-your-live';
const LAST_PROMPTED_KEY = 'updates:lastPromptedRelease';

export interface AppUpdate {
  version: string;
  tagName: string;
  notes: string;
  apkUrl: string | null;
  releaseUrl: string;
}

export function getCurrentAppVersion(): string {
  return Constants.expoConfig?.version ?? '1.0.0';
}

async function fetchWithTimeout(path: string, timeoutMs: number): Promise<Response> {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), timeoutMs);
  try {
    return await fetch(`${GITEA_BASE_URL}${path}`, { signal: controller.signal });
  } finally {
    clearTimeout(timer);
  }
}

export async function fetchLatestRelease(): Promise<AppUpdate | null> {
  try {
    const response = await fetchWithTimeout(
      `/api/v1/repos/${GITEA_OWNER}/${GITEA_REPO}/releases/latest`,
      8000,
    );
    if (!response.ok) return null;
    const release = await response.json();
    const apkAsset = (release.assets ?? []).find(
      (asset: { name?: string }) => asset.name && /\.apk$/i.test(asset.name),
    );
    const tagName: string = release.tag_name ?? release.name ?? '';
    return {
      version: tagName.replace(/^v/i, ''),
      tagName,
      notes: release.body ?? '',
      apkUrl: apkAsset?.browser_download_url ?? null,
      releaseUrl:
        release.html_url ??
        `${GITEA_BASE_URL}/${GITEA_OWNER}/${GITEA_REPO}/releases/tag/${tagName}`,
    };
  } catch {
    return null;
  }
}

export function compareVersions(a: string, b: string): number {
  const parse = (value: string) =>
    value.split('.').map((part) => parseInt(part.replace(/\D/g, ''), 10) || 0);
  const left = parse(a);
  const right = parse(b);
  const length = Math.max(left.length, right.length);
  for (let i = 0; i < length; i++) {
    const x = left[i] ?? 0;
    const y = right[i] ?? 0;
    if (x > y) return 1;
    if (x < y) return -1;
  }
  return 0;
}

export async function checkForUpdates(): Promise<AppUpdate | null> {
  const release = await fetchLatestRelease();
  if (!release) return null;
  if (compareVersions(release.version, getCurrentAppVersion()) <= 0) return null;
  return release;
}

export async function wasPromptedFor(tagName: string): Promise<boolean> {
  try {
    const stored = await AsyncStorage.getItem(LAST_PROMPTED_KEY);
    return stored === tagName;
  } catch {
    return false;
  }
}

export async function markPrompted(tagName: string): Promise<void> {
  try {
    await AsyncStorage.setItem(LAST_PROMPTED_KEY, tagName);
  } catch {
    // ignore
  }
}