import { logApiError } from "@/lib/api/security";
import { NextResponse } from "next/server";
import { createRouteClient } from "@/lib/supabase/route";
import { sql } from "@/lib/db/postgres";
import { logTeamAudit } from "@/lib/team-audit";
import type { TeamInvitation } from "@/types";

function getInviteUrl(req: Request, token: string) {
  const configuredBaseUrl = process.env.NEXT_PUBLIC_APP_URL?.replace(/\/$/, "");
  const origin = configuredBaseUrl || new URL(req.url).origin;
  return `${origin}/teams?invite=${encodeURIComponent(token)}`;
}

async function sendInviteEmail(input: {
  apiKey: string;
  from: string;
  to: string;
  teamName: string;
  role: string;
  inviteUrl: string;
  inviterName: string;
  message: string;
}) {
  const html = `
    <div style="font-family: Inter, Arial, sans-serif; line-height: 1.5; color: #111827;">
      <h2 style="margin-bottom: 8px;">You have been invited to join ${input.teamName}</h2>
      <p style="margin: 0 0 12px;">
        ${input.inviterName} invited you to join <strong>${input.teamName}</strong> as <strong>${input.role}</strong>.
      </p>
      ${
        input.message
          ? `<p style="margin: 0 0 12px; padding: 12px; background: #f3f4f6; border-radius: 10px;">${input.message}</p>`
          : ""
      }
      <p style="margin: 0 0 18px;">
        Use the link below to accept the invite inside Mindavio:
      </p>
      <p style="margin: 0 0 20px;">
        <a href="${input.inviteUrl}" style="display: inline-block; background: #4f46e5; color: white; text-decoration: none; padding: 10px 16px; border-radius: 10px;">
          Accept invitation
        </a>
      </p>
      <p style="margin: 0; color: #6b7280; font-size: 14px;">
        If the button does not work, open this link manually:<br />
        <a href="${input.inviteUrl}">${input.inviteUrl}</a>
      </p>
    </div>
  `;

  const res = await fetch("https://api.resend.com/emails", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${input.apiKey}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      from: input.from,
      to: [input.to],
      subject: `Invitation to join ${input.teamName} on Mindavio`,
      html,
    }),
  });

  if (!res.ok) {
    const errorText = await res.text();
    throw new Error(errorText || "Invite email could not be sent");
  }
}

export async function POST(req: Request) {
  try {
    const supabase = await createRouteClient();
    const {
      data: { user },
    } = await supabase.auth.getUser();

    if (!user) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    const body = await req.json();
    const teamId = String(body.teamId || "");
    const email = String(body.email || "").trim().toLowerCase();
    const role = String(body.role || "member");
    const message = String(body.message || "").trim();

    if (!teamId || !email) {
      return NextResponse.json(
        { error: "Missing team or email" },
        { status: 400 }
      );
    }

    const { rows: teamRows } = await sql`
      SELECT * FROM teams WHERE id = ${teamId} LIMIT 1
    `;
    const team = teamRows[0];

    if (!team) {
      return NextResponse.json({ error: "Team not found" }, { status: 404 });
    }

    const { rows: profileRows } = await sql`
      SELECT full_name, email FROM profiles WHERE id = ${user.id} LIMIT 1
    `;
    const actorProfile = profileRows[0] ?? null;

    let invitation: TeamInvitation;
    try {
      const { rows: insertRows } = await sql`
        INSERT INTO team_invitations (team_id, email, role, invited_by, message)
        VALUES (${teamId}, ${email}, ${role}, ${user.id}, ${message})
        RETURNING *
      `;
      invitation = insertRows[0] as unknown as TeamInvitation;
    } catch (insertError) {
      const msg = insertError instanceof Error ? insertError.message : "Invitation could not be created";
      return NextResponse.json({ error: msg }, { status: 400 });
    }

    const inviteUrl = getInviteUrl(req, invitation.token);
    let delivery: "email_sent" | "stored_only" = "stored_only";

    const resendApiKey = process.env.RESEND_API_KEY;
    const inviteFromEmail = process.env.INVITE_FROM_EMAIL;

    if (resendApiKey && inviteFromEmail) {
      try {
        await sendInviteEmail({
          apiKey: resendApiKey,
          from: inviteFromEmail,
          to: email,
          teamName: String(team.name),
          role,
          inviteUrl,
          inviterName:
            (actorProfile?.full_name as string) || (actorProfile?.email as string) || "A teammate",
          message,
        });

        await sql`
          UPDATE team_invitations SET sent_at = ${new Date().toISOString()} WHERE id = ${invitation.id}
        `;

        delivery = "email_sent";
      } catch (emailError) {
        logApiError("Invite email delivery failed", emailError);
      }
    }

    await logTeamAudit(supabase, {
      teamId,
      actorId: user.id,
      action: "invite_created",
      entityType: "invite",
      entityId: invitation.id,
      title: email,
      details: {
        role,
        delivery,
      },
    });

    return NextResponse.json({
      invitation: {
        ...invitation,
        sent_at:
          delivery === "email_sent"
            ? new Date().toISOString()
            : invitation.sent_at,
      },
      inviteUrl,
      delivery,
    });
  } catch (error) {
    logApiError("Team invitation POST error:", error);
    return NextResponse.json(
      { error: "Invitation could not be sent" },
      { status: 500 }
    );
  }
}
