const BASE = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:8000";

// ── Types ─────────────────────────────────────────────────────────────────────

export type Plan = "free" | "pro" | "pro_max";
export type JobStatus = "queued" | "processing" | "completed" | "failed";

export interface TokenResponse {
  access_token: string;
  refresh_token: string;
  token_type: string;
}

export interface SignupResponse {
  email: string;
  message: string;
}

export interface UserResponse {
  id: number;
  email: string;
  name: string;
  plan: Plan;
  is_admin: boolean;
  email_verified: boolean;
  videos_used_today: number;
  created_at: string;
}

export interface PlanLimitsResponse {
  plan: Plan;
  videos_per_day: number;
  videos_used_today: number;
  videos_remaining: number;
  max_duration_minutes: number;
  priority_processing: boolean;
  download_transcript: boolean;
  api_access: boolean;
}

export interface ClipAnalysis {
  sentiment: string | null;
  emotion: Record<string, unknown> | null;
  tone: string | null;
  viral_score: number;
  viral_reason: string | null;
  hook: string | null;
  target_audience: string | null;
  best_platform: string | null;
  content_type: string | null;
  engagement_triggers: string[];
}

export interface ClipResult {
  start: number;
  end: number;
  text: string;
  analysis: ClipAnalysis;
  clip_filename: string | null;
}

export interface JobResponse {
  id: number;
  youtube_url: string;
  language: string;
  clip_type: string;
  status: JobStatus;
  error_message: string | null;
  video_title: string | null;
  duration_seconds: number | null;
  clips: ClipResult[] | null;
  created_at: string;
  completed_at: string | null;
}

export interface JobListItem {
  id: number;
  youtube_url: string;
  video_title: string | null;
  status: JobStatus;
  created_at: string;
  completed_at: string | null;
}

export interface CreateJobRequest {
  youtube_url: string;
  language?: string;
  whisper_model?: string;
  clip_type?: string;
  clip_duration?: number;
  top_n?: number;
  min_score?: number;
}

export interface TestimonialResponse {
  id: number;
  name: string;
  role: string;
  content: string;
  rating: number;
  avatar: string;
  sort_order: number;
  is_active: boolean;
  created_at: string;
  updated_at: string;
}

export interface TestimonialInput {
  name: string;
  role: string;
  content: string;
  rating: number;
  avatar?: string;
  sort_order: number;
  is_active: boolean;
}

export interface PlanFeature {
  label: string;
  included: boolean;
}

export interface PlanCatalogResponse {
  id: number;
  plan_key: Plan;
  name: string;
  description: string;
  price_monthly: number | null;
  price_yearly: number | null;
  cta_label: string;
  cta_href: string;
  features: PlanFeature[];
  is_popular: boolean;
  is_active: boolean;
  sort_order: number;
  created_at: string;
  updated_at: string;
}

export interface PlanCatalogInput {
  name: string;
  description: string;
  price_monthly: number | null;
  price_yearly: number | null;
  cta_label: string;
  cta_href: string;
  features: PlanFeature[];
  is_popular: boolean;
  is_active: boolean;
  sort_order: number;
}

export interface ContactSubmissionRequest {
  name: string;
  email: string;
  subject: string;
  message: string;
}

export interface ContactSubmissionCreateResponse {
  id: number;
  message: string;
}

export interface ContactSubmissionResponse {
  id: number;
  name: string;
  email: string;
  subject: string;
  message: string;
  is_read: boolean;
  created_at: string;
}

// ── HTTP helper ───────────────────────────────────────────────────────────────

class ApiError extends Error {
  constructor(
    public status: number,
    message: string
  ) {
    super(message);
    this.name = "ApiError";
  }
}

async function request<T>(
  path: string,
  options: RequestInit & { token?: string } = {}
): Promise<T> {
  const { token, ...init } = options;
  const headers: Record<string, string> = {
    "Content-Type": "application/json",
    ...(init.headers as Record<string, string>),
  };
  if (token) headers["Authorization"] = `Bearer ${token}`;

  const res = await fetch(`${BASE}${path}`, { ...init, headers });

  if (!res.ok) {
    let detail = res.statusText;
    try {
      const body = await res.json();
      detail = body.detail ?? detail;
    } catch {
      // ignore parse error
    }
    throw new ApiError(res.status, detail);
  }

  if (res.status === 204) return undefined as T;
  return res.json();
}

// ── Auth API ──────────────────────────────────────────────────────────────────

export const authApi = {
  signup(name: string, email: string, password: string) {
    return request<SignupResponse>("/auth/signup", {
      method: "POST",
      body: JSON.stringify({ name, email, password }),
    });
  },

  verifyEmail(email: string, otp: string) {
    return request<TokenResponse>("/auth/verify-email", {
      method: "POST",
      body: JSON.stringify({ email, otp }),
    });
  },

  googleLogin(credential: string) {
    return request<TokenResponse>("/auth/google", {
      method: "POST",
      body: JSON.stringify({ credential }),
    });
  },

  resendVerification(email: string) {
    return request<SignupResponse>("/auth/resend-verification", {
      method: "POST",
      body: JSON.stringify({ email }),
    });
  },

  login(email: string, password: string) {
    return request<TokenResponse>("/auth/login", {
      method: "POST",
      body: JSON.stringify({ email, password }),
    });
  },

  refresh(refreshToken: string) {
    return request<TokenResponse>("/auth/refresh", {
      method: "POST",
      body: JSON.stringify({ refresh_token: refreshToken }),
    });
  },
};

// ── User API ──────────────────────────────────────────────────────────────────

export const userApi = {
  getMe(token: string) {
    return request<UserResponse>("/users/me", { token });
  },

  updateMe(token: string, data: { name?: string; email?: string }) {
    return request<UserResponse>("/users/me", {
      method: "PUT",
      token,
      body: JSON.stringify(data),
    });
  },

  getLimits(token: string) {
    return request<PlanLimitsResponse>("/users/me/limits", { token });
  },
};

// ── Jobs API ──────────────────────────────────────────────────────────────────

export const jobsApi = {
  create(token: string, data: CreateJobRequest) {
    return request<JobResponse>("/jobs", {
      method: "POST",
      token,
      body: JSON.stringify(data),
    });
  },

  list(token: string) {
    return request<JobListItem[]>("/jobs", { token });
  },

  get(token: string, jobId: number) {
    return request<JobResponse>(`/jobs/${jobId}`, { token });
  },

  delete(token: string, jobId: number) {
    return request<void>(`/jobs/${jobId}`, { method: "DELETE", token });
  },

  getTranscript(token: string, jobId: number) {
    return request<{ job_id: number; transcript: string }>(`/jobs/${jobId}/transcript`, { token });
  },

  /** Returns a blob URL for downloading clip video. Caller must revoke it. */
  async downloadClip(token: string, jobId: number, clipIndex: number): Promise<string> {
    const res = await fetch(`${BASE}/jobs/${jobId}/clips/${clipIndex}`, {
      headers: { Authorization: `Bearer ${token}` },
    });
    if (!res.ok) {
      const body = await res.json().catch(() => ({}));
      throw new ApiError(res.status, body.detail ?? res.statusText);
    }
    const blob = await res.blob();
    return URL.createObjectURL(blob);
  },
};

// ── Public API ────────────────────────────────────────────────────────────────

export interface FaqResponse {
  id: number;
  question: string;
  answer: string;
  sort_order: number;
  is_active: boolean;
  created_at: string;
  updated_at: string;
}

export interface FaqInput {
  question: string;
  answer: string;
  sort_order: number;
  is_active: boolean;
}

export const publicApi = {
  getTestimonials() {
    return request<TestimonialResponse[]>("/testimonials");
  },

  getFaqs() {
    return request<FaqResponse[]>("/faqs");
  },

  getPlans() {
    return request<PlanCatalogResponse[]>("/plans");
  },

  submitContact(data: ContactSubmissionRequest) {
    return request<ContactSubmissionCreateResponse>("/contact", {
      method: "POST",
      body: JSON.stringify(data),
    });
  },
};

// ── Admin Types ───────────────────────────────────────────────────────────────

export interface AdminStatsResponse {
  total_users: number;
  admin_users: number;
  active_users: number;
  free_users: number;
  pro_users: number;
  pro_max_users: number;
  total_jobs: number;
  jobs_today: number;
  jobs_processing: number;
}

export interface AdminSettings {
  maintenance_mode: boolean;
  new_signups: boolean;
  free_plan_enabled: boolean;
  email_notifications: boolean;
  api_access_enabled: boolean;
  watermark_enabled: boolean;
  free_daily_limit: number;
  free_max_minutes: number;
  free_max_clips: number;
  pro_daily_limit: number;
  pro_max_minutes: number;
  pro_max_clips: number;
}

export interface AdminUserResponse {
  id: number;
  email: string;
  name: string;
  plan: Plan;
  is_active: boolean;
  is_admin: boolean;
  videos_used_today: number;
  created_at: string;
  total_jobs: number;
}

export interface AdminJobResponse {
  id: number;
  user_id: number;
  user_email: string;
  youtube_url: string;
  video_title: string | null;
  status: JobStatus;
  duration_seconds: number | null;
  created_at: string;
  completed_at: string | null;
}

// ── Admin API ─────────────────────────────────────────────────────────────────

export const adminApi = {
  getStats(token: string) {
    return request<AdminStatsResponse>("/admin/stats", { token });
  },

  getUsers(token: string) {
    return request<AdminUserResponse[]>("/admin/users", { token });
  },

  updateUserPlan(token: string, userId: number, plan: Plan) {
    return request<AdminUserResponse>(`/admin/users/${userId}/plan`, {
      method: "PUT",
      token,
      body: JSON.stringify({ plan }),
    });
  },

  toggleUserActive(token: string, userId: number, is_active: boolean) {
    return request<AdminUserResponse>(`/admin/users/${userId}/active`, {
      method: "PUT",
      token,
      body: JSON.stringify({ is_active }),
    });
  },

  getJobs(token: string) {
    return request<AdminJobResponse[]>("/admin/jobs", { token });
  },

  getSettings(token: string) {
    return request<AdminSettings>("/admin/settings", { token });
  },

  updateSettings(token: string, data: AdminSettings) {
    return request<AdminSettings>("/admin/settings", {
      method: "PUT",
      token,
      body: JSON.stringify(data),
    });
  },

  getTestimonials(token: string) {
    return request<TestimonialResponse[]>("/admin/testimonials", { token });
  },

  createTestimonial(token: string, data: TestimonialInput) {
    return request<TestimonialResponse>("/admin/testimonials", {
      method: "POST",
      token,
      body: JSON.stringify(data),
    });
  },

  updateTestimonial(token: string, id: number, data: Partial<TestimonialInput>) {
    return request<TestimonialResponse>(`/admin/testimonials/${id}`, {
      method: "PUT",
      token,
      body: JSON.stringify(data),
    });
  },

  deleteTestimonial(token: string, id: number) {
    return request<void>(`/admin/testimonials/${id}`, {
      method: "DELETE",
      token,
    });
  },

  getFaqs(token: string) {
    return request<FaqResponse[]>("/admin/faqs", { token });
  },

  createFaq(token: string, data: FaqInput) {
    return request<FaqResponse>("/admin/faqs", {
      method: "POST",
      token,
      body: JSON.stringify(data),
    });
  },

  updateFaq(token: string, id: number, data: Partial<FaqInput>) {
    return request<FaqResponse>(`/admin/faqs/${id}`, {
      method: "PUT",
      token,
      body: JSON.stringify(data),
    });
  },

  deleteFaq(token: string, id: number) {
    return request<void>(`/admin/faqs/${id}`, {
      method: "DELETE",
      token,
    });
  },

  getPlans(token: string) {
    return request<PlanCatalogResponse[]>("/admin/plans", { token });
  },

  updatePlan(token: string, planKey: Plan, data: Partial<PlanCatalogInput>) {
    return request<PlanCatalogResponse>(`/admin/plans/${planKey}`, {
      method: "PUT",
      token,
      body: JSON.stringify(data),
    });
  },

  getContactSubmissions(token: string) {
    return request<ContactSubmissionResponse[]>("/admin/contact-submissions", { token });
  },

  markContactSubmissionRead(token: string, id: number) {
    return request<ContactSubmissionResponse>(`/admin/contact-submissions/${id}/read`, {
      method: "PUT",
      token,
    });
  },
};

export { ApiError };
