import type { Id } from "./_generated/dataModel"
import { mutation } from "./_generated/server"

export const seedDemo = mutation({
  args: {},
  handler: async (ctx) => {
    const tenantId = "tenant-atlas";
    const desiredQueues = [
      { name: "Chamados", slug: "chamados" },
      { name: "Laboratório", slug: "laboratorio" },
      { name: "Visitas", slug: "visitas" },
    ];

    // Ensure queues
    const existingQueues = await ctx.db
      .query("queues")
      .withIndex("by_tenant", (q) => q.eq("tenantId", tenantId))
      .collect();

    const normalizedQueues = await Promise.all(
      existingQueues.map(async (queue) => {
        if (!queue) return queue;
        if (queue.name === "Suporte N1" || queue.slug === "suporte-n1") {
          await ctx.db.patch(queue._id, { name: "Chamados", slug: "chamados" });
          return (await ctx.db.get(queue._id)) ?? queue;
        }
        if (queue.name === "Suporte N2" || queue.slug === "suporte-n2") {
          await ctx.db.patch(queue._id, { name: "Laboratório", slug: "laboratorio" });
          return (await ctx.db.get(queue._id)) ?? queue;
        }
        return queue;
      })
    );

    const presentQueues = normalizedQueues.filter(
      (queue): queue is NonNullable<(typeof normalizedQueues)[number]> => Boolean(queue)
    );
    const queuesBySlug = new Map(presentQueues.map((queue) => [queue.slug, queue]));
    const queuesByName = new Map(presentQueues.map((queue) => [queue.name, queue]));
    const queues = [] as typeof presentQueues;

    for (const def of desiredQueues) {
      let queue = queuesBySlug.get(def.slug) ?? queuesByName.get(def.name);
      if (!queue) {
        const newId = await ctx.db.insert("queues", { tenantId, name: def.name, slug: def.slug, teamId: undefined });
        queue = (await ctx.db.get(newId))!;
        queuesBySlug.set(queue.slug, queue);
        queuesByName.set(queue.name, queue);
      }
      queues.push(queue);
    }

    const queueChamados = queuesBySlug.get("chamados");
    const queueLaboratorio = queuesBySlug.get("laboratorio");
    const queueVisitas = queuesBySlug.get("visitas");
    if (!queueChamados || !queueLaboratorio || !queueVisitas) {
      throw new Error("Filas padrão não foram inicializadas");
    }

    // Ensure users
    function slugify(value: string) {
      return value
        .normalize("NFD")
        .replace(/[\u0300-\u036f]/g, "")
        .replace(/[^\w\s-]/g, "")
        .trim()
        .replace(/\s+/g, "-")
        .replace(/-+/g, "-")
        .toLowerCase();
    }

    function defaultAvatar(name: string, email: string, role: string) {
      const normalizedRole = role.toUpperCase();
      if (normalizedRole === "MANAGER") {
        return `https://i.pravatar.cc/150?u=${encodeURIComponent(email)}`;
      }
      const first = name.split(" ")[0] ?? email;
      return `https://avatar.vercel.sh/${encodeURIComponent(first)}`;
    }

    async function ensureCompany(def: {
      name: string;
      slug?: string;
      cnpj?: string;
      domain?: string;
      phone?: string;
      description?: string;
      address?: string;
    }): Promise<Id<"companies">> {
      const slug = def.slug ?? slugify(def.name);
      const existing = await ctx.db
        .query("companies")
        .withIndex("by_tenant_slug", (q) => q.eq("tenantId", tenantId).eq("slug", slug))
        .first();
      const now = Date.now();
      const payload = {
        tenantId,
        name: def.name,
        slug,
        cnpj: def.cnpj ?? undefined,
        domain: def.domain ?? undefined,
        phone: def.phone ?? undefined,
        description: def.description ?? undefined,
        address: def.address ?? undefined,
        createdAt: now,
        updatedAt: now,
      };
      if (existing) {
        const updates: Record<string, unknown> = {};
        if (existing.name !== payload.name) updates.name = payload.name;
        if (existing.cnpj !== payload.cnpj) updates.cnpj = payload.cnpj;
        if (existing.domain !== payload.domain) updates.domain = payload.domain;
        if (existing.phone !== payload.phone) updates.phone = payload.phone;
        if (existing.description !== payload.description) updates.description = payload.description;
        if (existing.address !== payload.address) updates.address = payload.address;
        if (Object.keys(updates).length > 0) {
          updates.updatedAt = now;
          await ctx.db.patch(existing._id, updates);
        }
        return existing._id;
      }
      return await ctx.db.insert("companies", payload);
    }

    async function ensureUser(params: {
      name: string;
      email: string;
      role?: string;
      companyId?: Id<"companies">;
      avatarUrl?: string;
    }): Promise<Id<"users">> {
      const normalizedEmail = params.email.trim().toLowerCase();
      const normalizedRole = (params.role ?? "MANAGER").toUpperCase();
      const desiredAvatar = params.avatarUrl ?? defaultAvatar(params.name, normalizedEmail, normalizedRole);
      const existing = await ctx.db
        .query("users")
        .withIndex("by_tenant_email", (q) => q.eq("tenantId", tenantId).eq("email", normalizedEmail))
        .first();
      if (existing) {
        const updates: Record<string, unknown> = {};
        if (existing.name !== params.name) updates.name = params.name;
        if ((existing.role ?? "MANAGER") !== normalizedRole) updates.role = normalizedRole;
        if ((existing.avatarUrl ?? undefined) !== desiredAvatar) updates.avatarUrl = desiredAvatar;
        if ((existing.companyId ?? undefined) !== (params.companyId ?? undefined)) updates.companyId = params.companyId ?? undefined;
        if (Object.keys(updates).length > 0) {
          await ctx.db.patch(existing._id, updates);
        }
        return existing._id;
      }
      return await ctx.db.insert("users", {
        tenantId,
        name: params.name,
        email: normalizedEmail,
        role: normalizedRole,
        avatarUrl: desiredAvatar,
        companyId: params.companyId ?? undefined,
      });
    }

    const companiesSeed = [
      {
        name: "Atlas Engenharia Digital",
        slug: "atlas-engenharia",
        cnpj: "12.345.678/0001-90",
        domain: "atlasengenharia.com.br",
        phone: "+55 11 4002-8922",
        description: "Transformação digital para empresas de engenharia e construção.",
        address: "Av. Paulista, 1234 - Bela Vista, São Paulo/SP",
      },
      {
        name: "Omni Saúde Integrada",
        slug: "omni-saude",
        cnpj: "45.678.912/0001-05",
        domain: "omnisaude.com.br",
        phone: "+55 31 3555-7788",
        description: "Rede de clínicas com serviços de telemedicina e prontuário eletrônico.",
        address: "Rua da Bahia, 845 - Centro, Belo Horizonte/MG",
      },
    ];

    const companyIds = new Map<string, Id<"companies">>();
    for (const company of companiesSeed) {
      const id = await ensureCompany(company);
      companyIds.set(company.slug, id);
    }

    const adminId = await ensureUser({ name: "Administrador", email: "admin@sistema.dev", role: "ADMIN" });
    const staffRoster = [
      { name: "Gabriel Oliveira", email: "gabriel.oliveira@rever.com.br" },
      { name: "George Araujo", email: "george.araujo@rever.com.br" },
      { name: "Hugo Soares", email: "hugo.soares@rever.com.br" },
      { name: "Julio Cesar", email: "julio@rever.com.br" },
      { name: "Lorena Magalhães", email: "lorena@rever.com.br" },
      { name: "Rever", email: "renan.pac@paulicon.com.br" },
      { name: "Thiago Medeiros", email: "thiago.medeiros@rever.com.br" },
      { name: "Weslei Magalhães", email: "weslei@rever.com.br" },
    ];

    const staffIds = await Promise.all(
      staffRoster.map((staff) => ensureUser({ name: staff.name, email: staff.email, role: "AGENT" })),
    );
    const defaultAssigneeId = staffIds[0] ?? adminId;

    const atlasCompanyId = companyIds.get("atlas-engenharia");
    const omniCompanyId = companyIds.get("omni-saude");
    if (!atlasCompanyId || !omniCompanyId) {
      throw new Error("Empresas padrão não foram inicializadas");
    }

    const atlasManagerId = await ensureUser({
      name: "Mariana Andrade",
      email: "mariana.andrade@atlasengenharia.com.br",
      role: "MANAGER",
      companyId: atlasCompanyId,
    });

    const joaoAtlasId = await ensureUser({
      name: "João Pedro Ramos",
      email: "joao.ramos@atlasengenharia.com.br",
      role: "MANAGER",
      companyId: atlasCompanyId,
    });
    await ensureUser({
      name: "Aline Rezende",
      email: "aline.rezende@atlasengenharia.com.br",
      role: "MANAGER",
      companyId: atlasCompanyId,
    });

    const omniManagerId = await ensureUser({
      name: "Fernanda Lima",
      email: "fernanda.lima@omnisaude.com.br",
      role: "MANAGER",
      companyId: omniCompanyId,
    });

    const ricardoOmniId = await ensureUser({
      name: "Ricardo Matos",
      email: "ricardo.matos@omnisaude.com.br",
      role: "MANAGER",
      companyId: omniCompanyId,
    });
    await ensureUser({
      name: "Luciana Prado",
      email: "luciana.prado@omnisaude.com.br",
      role: "MANAGER",
      companyId: omniCompanyId,
    });
    const clienteDemoId = await ensureUser({
      name: "Cliente Demo",
      email: "cliente.demo@sistema.dev",
      role: "MANAGER",
      companyId: omniCompanyId,
    });

    const templateDefinitions = [
      {
        title: "A Rever agradece seu contato",
        body: "<p>A Rever agradece seu contato. Recebemos sua solicitação e nossa equipe já está analisando os detalhes. Retornaremos com atualizações em breve.</p>",
      },
      {
        title: "Atualização do chamado",
        body: "<p>Seu chamado foi atualizado. Caso tenha novas informações ou dúvidas, basta responder a esta mensagem.</p>",
      },
      {
        title: "Chamado resolvido",
        body: "<p>Concluímos o atendimento deste chamado. A Rever agradece a parceria e permanecemos à disposição para novos suportes.</p>",
      },
    ];

    const existingTemplates = await ctx.db
      .query("commentTemplates")
      .withIndex("by_tenant", (q) => q.eq("tenantId", tenantId))
      .collect();

    for (const definition of templateDefinitions) {
      const already = existingTemplates.find((template) => template?.title === definition.title);
      if (already) continue;
      const timestamp = Date.now();
      await ctx.db.insert("commentTemplates", {
        tenantId,
        title: definition.title,
        body: definition.body,
        createdBy: adminId,
        updatedBy: adminId,
        createdAt: timestamp,
        updatedAt: timestamp,
      });
    }

    // Seed a couple of tickets
    const now = Date.now();
    const newestRef = await ctx.db
      .query("tickets")
      .withIndex("by_tenant_reference", (q) => q.eq("tenantId", tenantId))
      .order("desc")
      .take(1);
    let ref = newestRef[0]?.reference ?? 41000;
    const queue1 = queueChamados._id;
    const queue2 = queueLaboratorio._id;

    const t1 = await ctx.db.insert("tickets", {
      tenantId,
      reference: ++ref,
      subject: "Erro 500 ao acessar portal do cliente",
      summary: "Clientes relatam erro intermitente no portal web",
      status: "AWAITING_ATTENDANCE",
      priority: "URGENT",
      channel: "EMAIL",
      queueId: queue1,
      requesterId: joaoAtlasId,
      assigneeId: defaultAssigneeId,
      companyId: atlasCompanyId,
      createdAt: now - 1000 * 60 * 60 * 5,
      updatedAt: now - 1000 * 60 * 10,
      tags: ["portal", "cliente"],
    });
    await ctx.db.insert("ticketEvents", {
      ticketId: t1,
      type: "CREATED",
      createdAt: now - 1000 * 60 * 60 * 5,
      payload: {},
    });
    await ctx.db.insert("ticketEvents", {
      ticketId: t1,
      type: "MANAGER_NOTIFIED",
      createdAt: now - 1000 * 60 * 60 * 4,
      payload: { managerUserId: atlasManagerId },
    });

    const t2 = await ctx.db.insert("tickets", {
      tenantId,
      reference: ++ref,
      subject: "Integração ERP parada",
      summary: "Webhook do ERP retornando timeout",
      status: "PENDING",
      priority: "HIGH",
      channel: "WHATSAPP",
      queueId: queue2,
      requesterId: ricardoOmniId,
      assigneeId: defaultAssigneeId,
      companyId: omniCompanyId,
      createdAt: now - 1000 * 60 * 60 * 8,
      updatedAt: now - 1000 * 60 * 30,
      tags: ["Integração", "erp"],
    });
    await ctx.db.insert("ticketEvents", {
      ticketId: t2,
      type: "CREATED",
      createdAt: now - 1000 * 60 * 60 * 8,
      payload: {},
    });
    await ctx.db.insert("ticketEvents", {
      ticketId: t2,
      type: "MANAGER_NOTIFIED",
      createdAt: now - 1000 * 60 * 60 * 7,
      payload: { managerUserId: omniManagerId },
    });

    const t3 = await ctx.db.insert("tickets", {
      tenantId,
      reference: ++ref,
      subject: "Visita técnica para instalação de roteadores",
      summary: "Equipe Omni solicita agenda para instalação de novos pontos de rede",
      status: "AWAITING_ATTENDANCE",
      priority: "MEDIUM",
      channel: "PHONE",
      queueId: queueVisitas._id,
      requesterId: clienteDemoId,
      assigneeId: defaultAssigneeId,
      companyId: omniCompanyId,
      createdAt: now - 1000 * 60 * 60 * 3,
      updatedAt: now - 1000 * 60 * 20,
      tags: ["visita", "infraestrutura"],
    });
    await ctx.db.insert("ticketEvents", {
      ticketId: t3,
      type: "CREATED",
      createdAt: now - 1000 * 60 * 60 * 3,
      payload: {},
    });
    await ctx.db.insert("ticketEvents", {
      ticketId: t3,
      type: "VISIT_SCHEDULED",
      createdAt: now - 1000 * 60 * 15,
      payload: { scheduledFor: now + 1000 * 60 * 60 * 24 },
    });
  },
});
