import { logApiError } from "@/lib/api/security";
import { NextResponse } from "next/server";
import { canAccessWorkspace } from "@/lib/developers/auth";
import {
  decryptGitHubToken,
  getGitHubIssue,
  updateGitHubIssue,
} from "@/lib/integrations/github";
import { createAdminClient } from "@/lib/supabase/admin";
import { createRouteClient } from "@/lib/supabase/route";

export async function POST(
  req: Request,
  context: { params: Promise<{ id: string }> }
) {
  try {
    const supabase = await createRouteClient();
    const admin = createAdminClient();
    const {
      data: { user },
    } = await supabase.auth.getUser();

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

    const { id } = await context.params;
    const body = await req.json().catch(() => ({}));
    const direction = body.direction === "push" ? "push" : "pull";

    const { data: task } = await supabase
      .from("tasks")
      .select("id, user_id, team_id, status")
      .eq("id", id)
      .maybeSingle();

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

    const hasAccess =
      task.user_id === user.id && !task.team_id
        ? true
        : await canAccessWorkspace(user.id, task.team_id || null);

    if (!hasAccess) {
      return NextResponse.json({ error: "Forbidden" }, { status: 403 });
    }

    const { data: links } = await supabase
      .from("github_issue_links")
      .select("*")
      .eq("task_id", id);

    const typedLinks = links || [];
    if (typedLinks.length === 0) {
      return NextResponse.json({ synced: 0, taskStatus: task.status });
    }

    const connectionIds = Array.from(new Set(typedLinks.map((link) => link.connection_id)));
    const { data: connections } = await admin
      .from("integration_connections")
      .select("id, provider, secret_encrypted, is_active")
      .in("id", connectionIds)
      .eq("provider", "github");

    const connectionMap = new Map((connections || []).map((connection) => [connection.id, connection]));
    const nextStates: string[] = [];

    for (const link of typedLinks) {
      const connection = connectionMap.get(link.connection_id);
      if (!connection || !connection.is_active) continue;

      const token = decryptGitHubToken(connection.secret_encrypted);

      if (direction === "push") {
        const targetState = task.status === "done" || task.status === "cancelled" ? "closed" : "open";
        const issue = await updateGitHubIssue({
          token,
          owner: link.repo_owner,
          repo: link.repo_name,
          issueNumber: link.issue_number,
          state: targetState,
        });

        nextStates.push(issue.state);
        await supabase
          .from("github_issue_links")
          .update({ issue_state: issue.state, issue_title: issue.title, issue_url: issue.html_url })
          .eq("id", link.id);
      } else {
        const issue = await getGitHubIssue({
          token,
          owner: link.repo_owner,
          repo: link.repo_name,
          issueNumber: link.issue_number,
        });

        nextStates.push(issue.state);
        await supabase
          .from("github_issue_links")
          .update({ issue_state: issue.state, issue_title: issue.title, issue_url: issue.html_url })
          .eq("id", link.id);
      }
    }

    let nextTaskStatus = task.status;
    if (direction === "pull" && nextStates.length > 0) {
      const allClosed = nextStates.every((state) => state === "closed");
      const anyOpen = nextStates.some((state) => state === "open");

      if (allClosed && task.status !== "done") {
        nextTaskStatus = "done";
        await supabase
          .from("tasks")
          .update({
            status: "done",
            completed_at: new Date().toISOString(),
          })
          .eq("id", id);
      } else if (anyOpen && task.status === "done") {
        nextTaskStatus = "in_progress";
        await supabase
          .from("tasks")
          .update({
            status: "in_progress",
            completed_at: null,
          })
          .eq("id", id);
      }
    }

    return NextResponse.json({
      synced: nextStates.length,
      taskStatus: nextTaskStatus,
      direction,
    });
  } catch (error) {
    logApiError("Task GitHub sync POST error:", error);
    const message = error instanceof Error ? error.message : "GitHub sync failed";
    return NextResponse.json({ error: message }, { status: 500 });
  }
}
