import { API_BASE, request } from "./core";
import { User } from "./users";
import { LDAPConfig, LDAPTestResult } from "./ldap";

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

export interface Tenant {
  id: number;
  name: string;
  slug: string;
  active: boolean;
  created_at: string;
  domain_count?: number;
  user_count?: number;
  ldap_enabled?: boolean;
  ldap_url?: string;
  has_logo?: boolean;
}

export interface TenantUsageEntry {
  id: number;
  name: string;
  slug: string;
  max_storage_bytes: number | null;
  max_users: number | null;
  max_emails: number | null;
  storage_bytes: number;
  user_count: number;
  email_count: number;
}

export interface TenantDomain {
  id: number;
  tenant_id: number;
  domain: string;
  created_at: string;
}

export interface TenantDefaultUser {
  username: string;
  password: string;
  role: string;
}

export interface CreateTenantResponse extends Tenant {
  default_users: TenantDefaultUser[];
}

export interface TenantLDAPConfig extends LDAPConfig {
  tenant_id?: number;
}

export interface LDAPSyncResult {
  synced: number;
  errors: string[];
}

// ── Tenant CRUD ───────────────────────────────────────────────────────────────

export async function getTenants(): Promise<Tenant[]> {
  return request<Tenant[]>("/api/tenants");
}

export async function getTenantUsers(tenantId: number): Promise<User[]> {
  return request<User[]>(`/api/tenants/${tenantId}/users`);
}

export async function createTenant(name: string, slug: string): Promise<CreateTenantResponse> {
  return request<CreateTenantResponse>("/api/tenants", {
    method: "POST",
    body: JSON.stringify({ name, slug }),
  });
}

export async function updateTenant(
  id: number,
  data: { name?: string; active?: boolean }
): Promise<Tenant> {
  return request<Tenant>(`/api/tenants/${id}`, {
    method: "PATCH",
    body: JSON.stringify(data),
  });
}

export async function deleteTenant(id: number): Promise<void> {
  await request<void>(`/api/tenants/${id}`, { method: "DELETE" });
}

// ── Tenant Domains ────────────────────────────────────────────────────────────

export async function getTenantDomains(id: number): Promise<TenantDomain[]> {
  return request<TenantDomain[]>(`/api/tenants/${id}/domains`);
}

export async function addTenantDomain(
  tenantId: number,
  domain: string
): Promise<TenantDomain> {
  return request<TenantDomain>(`/api/tenants/${tenantId}/domains`, {
    method: "POST",
    body: JSON.stringify({ domain }),
  });
}

export async function removeTenantDomain(
  tenantId: number,
  domainId: number
): Promise<void> {
  await request<void>(`/api/tenants/${tenantId}/domains/${domainId}`, {
    method: "DELETE",
  });
}

// ── Tenant Logo ───────────────────────────────────────────────────────────────

export function getTenantLogoUrl(tenantId: number): string {
  return `${API_BASE}/api/tenants/${tenantId}/logo`;
}

export async function uploadTenantLogo(tenantId: number, file: File): Promise<void> {
  const form = new FormData();
  form.append("logo", file);
  const res = await fetch(`${API_BASE}/api/tenants/${tenantId}/logo`, {
    method: "POST",
    body: form,
    credentials: "include",
  });
  if (!res.ok) {
    const body = await res.text();
    throw new Error(body || `Upload failed: ${res.status}`);
  }
}

export async function deleteTenantLogo(tenantId: number): Promise<void> {
  await request<void>(`/api/tenants/${tenantId}/logo`, { method: "DELETE" });
}

// domain_admin: own tenant logo
export async function uploadMyTenantLogo(file: File): Promise<void> {
  const form = new FormData();
  form.append("logo", file);
  const res = await fetch(`${API_BASE}/api/tenant/logo`, {
    method: "POST",
    body: form,
    credentials: "include",
  });
  if (!res.ok) {
    const body = await res.text();
    throw new Error(body || `Upload failed: ${res.status}`);
  }
}

export async function deleteMyTenantLogo(): Promise<void> {
  await request<void>("/api/tenant/logo", { method: "DELETE" });
}

// ── Per-Tenant LDAP (domain_admin: own tenant) ────────────────────────────────

export async function getTenantLDAPConfig(): Promise<TenantLDAPConfig | null> {
  try {
    return await request<TenantLDAPConfig>("/api/tenant/ldap");
  } catch (e: unknown) {
    if (e instanceof Error && e.message.includes("404")) return null;
    if (e instanceof Error && e.message.includes("no ldap config")) return null;
    throw e;
  }
}

export async function saveTenantLDAPConfig(cfg: Partial<TenantLDAPConfig>): Promise<void> {
  await request<void>("/api/tenant/ldap", { method: "PUT", body: JSON.stringify(cfg) });
}

export async function deleteTenantLDAPConfig(): Promise<void> {
  await request<void>("/api/tenant/ldap", { method: "DELETE" });
}

export async function testTenantLDAPConfig(
  payload: { use_saved: boolean } & Partial<TenantLDAPConfig>
): Promise<LDAPTestResult> {
  return request<LDAPTestResult>("/api/tenant/ldap/test", {
    method: "POST",
    body: JSON.stringify(payload),
  });
}

// ── Per-Tenant LDAP (superadmin: arbitrary tenant) ────────────────────────────

export async function getAdminTenantLDAPConfig(tenantID: number): Promise<TenantLDAPConfig | null> {
  try {
    return await request<TenantLDAPConfig>(`/api/admin/tenants/${tenantID}/ldap`);
  } catch (e: unknown) {
    if (e instanceof Error && e.message.includes("404")) return null;
    if (e instanceof Error && e.message.includes("no ldap config")) return null;
    throw e;
  }
}

export async function saveAdminTenantLDAPConfig(tenantID: number, cfg: Partial<TenantLDAPConfig>): Promise<void> {
  await request<void>(`/api/admin/tenants/${tenantID}/ldap`, { method: "PUT", body: JSON.stringify(cfg) });
}

export async function deleteAdminTenantLDAPConfig(tenantID: number): Promise<void> {
  await request<void>(`/api/admin/tenants/${tenantID}/ldap`, { method: "DELETE" });
}

export async function testAdminTenantLDAPConfig(
  tenantID: number,
  payload: { use_saved: boolean } & Partial<TenantLDAPConfig>
): Promise<LDAPTestResult> {
  return request<LDAPTestResult>(`/api/admin/tenants/${tenantID}/ldap/test`, {
    method: "POST",
    body: JSON.stringify(payload),
  });
}

export async function syncAdminTenantLDAP(tenantID: number): Promise<LDAPSyncResult> {
  return request<LDAPSyncResult>(`/api/admin/tenants/${tenantID}/ldap/sync`, { method: "POST", body: "{}" });
}

// ── Tenant Quotas (PROJ-29) ───────────────────────────────────────────────────

export async function getAllTenantUsage(): Promise<TenantUsageEntry[]> {
  const data = await request<{ tenants: TenantUsageEntry[] }>("/api/admin/quotas");
  return data.tenants;
}

export async function setTenantQuota(
  tenantID: number,
  quota: { max_storage_bytes: number | null; max_users: number | null; max_emails: number | null }
): Promise<void> {
  await request<void>(`/api/admin/tenant/${tenantID}/quota`, {
    method: "PUT",
    body: JSON.stringify(quota),
  });
}
