"use server";

import { cookies } from "next/headers";
import { redirect } from "next/navigation";
import { AppwriteException, ID, Permission, Role, Query } from "node-appwrite";

import { createAdminClient, createSessionClient } from "./server";
import { DATABASE_ID, TABLES, type TenantKind } from "./schema";
import { ACTIVE_TENANT_COOKIE, type WorkspaceState } from "./tenant-types";

const MEMBER_NUMBER_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";

function generateMemberNumber(): string {
  let out = "";
  for (let i = 0; i < 6; i++) {
    out += MEMBER_NUMBER_ALPHABET[Math.floor(Math.random() * MEMBER_NUMBER_ALPHABET.length)];
  }
  return out;
}

async function reserveUniqueMemberNumber(
  tablesDB: ReturnType<typeof createAdminClient>["tablesDB"],
): Promise<string> {
  for (let attempt = 0; attempt < 8; attempt++) {
    const candidate = generateMemberNumber();
    const existing = await tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.tenantSettings,
      queries: [Query.equal("memberNumber", candidate), Query.limit(1)],
    });
    if (existing.total === 0) return candidate;
  }
  throw new Error("MEMBER_NUMBER_GENERATION_FAILED");
}

function appwriteError(e: unknown): string {
  if (e instanceof AppwriteException) {
    if (e.type === "team_already_exists") return "Bu isimde bir çalışma alanı zaten var.";
    if (e.type === "general_unauthorized_scope") return "Yetki hatası. Tekrar giriş yapın.";
    return e.message || "Beklenmeyen bir hata oluştu.";
  }
  return "Bağlantı hatası. Tekrar deneyin.";
}

async function setActiveTenantCookie(tenantId: string) {
  (await cookies()).set(ACTIVE_TENANT_COOKIE, tenantId, {
    path: "/",
    httpOnly: true,
    sameSite: "strict",
    secure: process.env.NODE_ENV === "production",
    maxAge: 60 * 60 * 24 * 365,
  });
}

export async function createWorkspaceAction(
  _prev: WorkspaceState,
  formData: FormData,
): Promise<WorkspaceState> {
  const companyName = String(formData.get("companyName") ?? "").trim();
  const companyTaxId = String(formData.get("companyTaxId") ?? "").trim() || undefined;
  const companyPhone = String(formData.get("companyPhone") ?? "").trim() || undefined;
  const rawKind = String(formData.get("kind") ?? "").trim();
  const kind: TenantKind | null =
    rawKind === "lab" || rawKind === "clinic" ? rawKind : null;

  if (!companyName) {
    return { ok: false, error: "Şirket adı zorunlu." };
  }
  if (!kind) {
    return { ok: false, error: "Klinik veya laboratuvar seçimi zorunlu." };
  }

  let teamId: string | null = null;
  const admin = createAdminClient();

  try {
    const session = await createSessionClient();
    const user = await session.account.get();

    const team = await session.teams.create(ID.unique(), companyName, ["owner"]);
    teamId = team.$id;

    const memberNumber = await reserveUniqueMemberNumber(admin.tablesDB);

    await admin.tablesDB.createRow(
      DATABASE_ID,
      TABLES.tenantSettings,
      ID.unique(),
      {
        tenantId: teamId,
        kind,
        memberNumber,
        companyName,
        companyTaxId,
        companyPhone,
      },
      [
        Permission.read(Role.team(teamId)),
        Permission.update(Role.team(teamId, "owner")),
        Permission.update(Role.team(teamId, "admin")),
        Permission.delete(Role.team(teamId, "owner")),
      ],
    );

    await session.account.updatePrefs({
      ...(user.prefs ?? {}),
      activeTenant: teamId,
    });

    await setActiveTenantCookie(teamId);
  } catch (e) {
    if (teamId) {
      try {
        await admin.teams.delete(teamId);
      } catch {
        // best-effort cleanup; original error is what we surface
      }
    }
    return { ok: false, error: appwriteError(e) };
  }

  redirect("/dashboard");
}

export async function importWorkspaceAction(
  _prev: WorkspaceState,
  formData: FormData,
): Promise<WorkspaceState> {
  const teamId = String(formData.get("teamId") ?? "").trim();
  const rawKind = String(formData.get("kind") ?? "").trim();
  const kind: TenantKind | null =
    rawKind === "lab" || rawKind === "clinic" ? rawKind : null;
  if (!teamId) return { ok: false, error: "Geçersiz istek." };
  if (!kind) return { ok: false, error: "Klinik veya laboratuvar seçimi zorunlu." };

  try {
    const { account, teams, tablesDB } = await createSessionClient();
    const user = await account.get();

    const allTeams = await teams.list();
    const team = allTeams.teams.find((t) => t.$id === teamId);
    if (!team) return { ok: false, error: "Çalışma alanı bulunamadı." };

    const existing = await tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.tenantSettings,
      queries: [Query.equal("tenantId", teamId), Query.limit(1)],
    });
    if (existing.total > 0) return { ok: false, error: "Bu çalışma alanı zaten mevcut." };

    const admin = createAdminClient();
    const memberNumber = await reserveUniqueMemberNumber(admin.tablesDB);

    await admin.tablesDB.createRow(
      DATABASE_ID,
      TABLES.tenantSettings,
      ID.unique(),
      {
        tenantId: teamId,
        kind,
        memberNumber,
        companyName: team.name,
        defaultCurrency: "TRY",
      },
      [
        Permission.read(Role.team(teamId)),
        Permission.update(Role.team(teamId, "owner")),
        Permission.update(Role.team(teamId, "admin")),
        Permission.delete(Role.team(teamId, "owner")),
      ],
    );

    await account.updatePrefs({ ...(user.prefs ?? {}), activeTenant: teamId });
    await setActiveTenantCookie(teamId);
  } catch (e) {
    return { ok: false, error: appwriteError(e) };
  }

  redirect("/dashboard");
}

export async function setActiveTenantAction(tenantId: string) {
  try {
    const { account, teams, tablesDB } = await createSessionClient();
    const user = await account.get();

    const allTeams = await teams.list();
    const isMember = allTeams.teams.some((t) => t.$id === tenantId);
    if (!isMember) {
      return { ok: false, error: "Bu çalışma alanına erişiminiz yok." };
    }

    // Verify this team belongs to this app (not a team from another KovakSoft product)
    const settingsCheck = await tablesDB.listRows({
      databaseId: DATABASE_ID,
      tableId: TABLES.tenantSettings,
      queries: [Query.equal("tenantId", tenantId), Query.limit(1)],
    });
    if (settingsCheck.total === 0) {
      return { ok: false, error: "Bu çalışma alanına erişiminiz yok." };
    }

    await account.updatePrefs({ ...(user.prefs ?? {}), activeTenant: tenantId });
    await setActiveTenantCookie(tenantId);
    return { ok: true };
  } catch (e) {
    return { ok: false, error: appwriteError(e) };
  }
}
