"use server";

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

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

function appwriteError(e: unknown): string {
  if (e instanceof AppwriteException) {
    switch (e.type) {
      case "user_invalid_credentials":
        return "Email veya şifre hatalı.";
      case "user_blocked":
        return "Hesabınız engellenmiş.";
      case "user_already_exists":
      case "user_email_already_exists":
        return "Bu email ile zaten bir hesap var.";
      case "user_password_mismatch":
        return "Şifreler eşleşmiyor.";
      case "general_rate_limit_exceeded":
        return "Çok fazla deneme. Birkaç dakika sonra tekrar deneyin.";
      default:
        return e.message || "Beklenmeyen bir hata oluştu.";
    }
  }
  if (process.env.NODE_ENV !== "production" && e instanceof Error) {
    return `Bağlantı hatası: ${e.message}`;
  }
  return "Bağlantı hatası. Tekrar deneyin.";
}

async function setSessionCookie(secret: string, expire: string) {
  (await cookies()).set(APPWRITE_SESSION_COOKIE, secret, {
    path: "/",
    httpOnly: true,
    sameSite: "strict",
    secure: process.env.NODE_ENV === "production",
    expires: new Date(expire),
  });
}

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,
  });
}

type LoginResolution =
  | { state: "no_tenants" }
  | { state: "mismatch"; existingKinds: TenantKind[] }
  | { state: "matched"; tenantId: string };

async function resolveTenantOnLogin(
  userId: string,
  kind: TenantKind,
): Promise<LoginResolution> {
  const { users, tablesDB } = createAdminClient();
  const memberships = await users.listMemberships({ userId });
  const teamIds = memberships.memberships.map((m) => m.teamId);
  if (teamIds.length === 0) return { state: "no_tenants" };

  const result = await tablesDB.listRows({
    databaseId: DATABASE_ID,
    tableId: TABLES.tenantSettings,
    queries: [Query.equal("tenantId", teamIds), Query.limit(50)],
  });
  const rows = result.rows as unknown as TenantSettings[];
  if (rows.length === 0) return { state: "no_tenants" };

  const match = rows.find((r) => r.kind === kind);
  if (match) return { state: "matched", tenantId: match.tenantId };

  const existingKinds = Array.from(new Set(rows.map((r) => r.kind)));
  return { state: "mismatch", existingKinds };
}

export async function signInAction(_prev: AuthState, formData: FormData): Promise<AuthState> {
  const email = String(formData.get("email") ?? "").trim();
  const password = String(formData.get("password") ?? "");
  const inviteCode = String(formData.get("inviteCode") ?? "").trim();
  const rawKind = String(formData.get("kind") ?? "").trim();
  const kind: TenantKind | null =
    rawKind === "lab" || rawKind === "clinic" ? rawKind : null;

  if (!email || !password) {
    return { ok: false, error: "Email ve şifre zorunlu." };
  }

  let sessionUserId: string | null = null;
  let sessionId: string | null = null;
  try {
    const { account } = createAdminClient();
    const session = await account.createEmailPasswordSession(email, password);
    sessionUserId = session.userId;
    sessionId = session.$id;
    await setSessionCookie(session.secret, session.expire);
  } catch (e) {
    console.error("[signInAction] createEmailPasswordSession", e);
    return { ok: false, error: appwriteError(e) };
  }

  // Invite flow short-circuits the kind check — invite code drives team membership
  if (inviteCode) {
    redirect(`/d/${inviteCode}`);
  }

  if (kind && sessionUserId) {
    let resolution: LoginResolution;
    try {
      resolution = await resolveTenantOnLogin(sessionUserId, kind);
    } catch (e) {
      console.error("[signInAction] resolveTenantOnLogin", e);
      // Tenant resolution failed: keep the session, send user to onboarding
      // so they can recover instead of getting locked out.
      redirect("/onboarding");
    }

    if (resolution.state === "no_tenants") {
      // Authenticated user with no workspace yet — carry the kind into onboarding
      redirect(`/onboarding?kind=${kind}`);
    }

    if (resolution.state === "mismatch") {
      try {
        const { users } = createAdminClient();
        if (sessionId) await users.deleteSession({ userId: sessionUserId, sessionId });
      } catch {
        /* best-effort */
      }
      (await cookies()).delete(APPWRITE_SESSION_COOKIE);
      const requested = kind === "lab" ? "laboratuvar" : "klinik";
      const existingLabel = resolution.existingKinds
        .map((k) => (k === "lab" ? "laboratuvar" : "klinik"))
        .join(" / ");
      return {
        ok: false,
        error: `Bu hesap ${existingLabel} olarak kayıtlı. ${requested} sekmesinden değil, ${existingLabel} sekmesinden giriş yapın.`,
      };
    }

    // matched
    await setActiveTenantCookie(resolution.tenantId);
    try {
      const { users } = createAdminClient();
      const user = await users.get({ userId: sessionUserId });
      await users.updatePrefs({
        userId: sessionUserId,
        prefs: {
          ...(user.prefs ?? {}),
          activeTenant: resolution.tenantId,
        },
      });
    } catch {
      /* best-effort */
    }
  }

  redirect("/dashboard");
}

export async function signUpAction(_prev: AuthState, formData: FormData): Promise<AuthState> {
  const name = String(formData.get("name") ?? "").trim();
  const email = String(formData.get("email") ?? "").trim();
  const password = String(formData.get("password") ?? "");
  const inviteCode = String(formData.get("inviteCode") ?? "").trim();

  if (!name || !email || !password) {
    return { ok: false, error: "Tüm alanlar zorunlu." };
  }
  if (password.length < 8) {
    return { ok: false, error: "Şifre en az 8 karakter olmalı." };
  }

  try {
    const { account } = createAdminClient();
    await account.create(ID.unique(), email, password, name);
    const session = await account.createEmailPasswordSession(email, password);
    await setSessionCookie(session.secret, session.expire);
  } catch (e) {
    return { ok: false, error: appwriteError(e) };
  }

  redirect(inviteCode ? `/d/${inviteCode}` : "/onboarding");
}

export async function forgotPasswordAction(
  _prev: AuthState,
  formData: FormData,
): Promise<AuthState> {
  const email = String(formData.get("email") ?? "").trim();
  if (!email) return { ok: false, error: "Email zorunlu." };

  try {
    const { account } = createAdminClient();
    const recoveryUrl = `${process.env.APP_URL ?? "http://localhost:3000"}/reset-password`;
    await account.createRecovery(email, recoveryUrl);
    return { ok: true };
  } catch (e) {
    return { ok: false, error: appwriteError(e) };
  }
}

export async function signOutAction() {
  try {
    const { account } = await createSessionClient();
    await account.deleteSession("current");
  } catch {
    // ignore — cookie will be cleared anyway
  }
  (await cookies()).delete(APPWRITE_SESSION_COOKIE);
  redirect("/sign-in");
}
