import { AuditAction, AuditResourceType, recordAudit } from '@sim/audit'
import { db } from '@sim/db'
import { member, user } from '@sim/db/schema'
import { createLogger } from '@sim/logger'
import { and, eq } from 'drizzle-orm'
import { type NextRequest, NextResponse } from 'next/server'
import { transferOwnershipContract } from '@/lib/api/contracts/organization'
import { parseRequest } from '@/lib/api/server'
import { getSession } from '@/lib/auth'
import { setActiveOrganizationForCurrentSession } from '@/lib/auth/active-organization'
import {
  removeUserFromOrganization,
  transferOrganizationOwnership,
} from '@/lib/billing/organizations/membership'
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'

const logger = createLogger('TransferOwnershipAPI')

export const POST = withRouteHandler(
  async (request: NextRequest, context: { params: Promise<{ id: string }> }) => {
    try {
      const session = await getSession()
      if (!session?.user?.id) {
        return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
      }

      const parsed = await parseRequest(transferOwnershipContract, request, context)
      if (!parsed.success) return parsed.response

      const { id: organizationId } = parsed.data.params
      const { newOwnerUserId, alsoLeave } = parsed.data.body

      if (newOwnerUserId === session.user.id) {
        return NextResponse.json(
          { error: 'New owner must differ from current owner' },
          { status: 400 }
        )
      }

      const [currentOwnerMember] = await db
        .select({ role: member.role })
        .from(member)
        .where(and(eq(member.organizationId, organizationId), eq(member.userId, session.user.id)))
        .limit(1)

      if (!currentOwnerMember) {
        return NextResponse.json(
          { error: 'You are not a member of this organization' },
          { status: 403 }
        )
      }

      if (currentOwnerMember.role !== 'owner') {
        return NextResponse.json(
          { error: 'Only the current owner can transfer ownership' },
          { status: 403 }
        )
      }

      const [targetMember] = await db
        .select({
          id: member.id,
          role: member.role,
          email: user.email,
          name: user.name,
        })
        .from(member)
        .innerJoin(user, eq(member.userId, user.id))
        .where(and(eq(member.organizationId, organizationId), eq(member.userId, newOwnerUserId)))
        .limit(1)

      if (!targetMember) {
        return NextResponse.json(
          { error: 'Target user is not a member of this organization' },
          { status: 400 }
        )
      }

      const transferResult = await transferOrganizationOwnership({
        organizationId,
        currentOwnerUserId: session.user.id,
        newOwnerUserId,
      })

      if (!transferResult.success) {
        return NextResponse.json(
          { error: transferResult.error ?? 'Failed to transfer ownership' },
          { status: 500 }
        )
      }

      recordAudit({
        workspaceId: null,
        actorId: session.user.id,
        actorName: session.user.name ?? undefined,
        actorEmail: session.user.email ?? undefined,
        action: AuditAction.ORG_MEMBER_ROLE_CHANGED,
        resourceType: AuditResourceType.ORGANIZATION,
        resourceId: organizationId,
        description: `Transferred ownership to ${targetMember.email}`,
        metadata: {
          targetUserId: newOwnerUserId,
          targetEmail: targetMember.email ?? undefined,
          targetName: targetMember.name ?? undefined,
          workspacesReassigned: transferResult.workspacesReassigned,
          billedAccountReassigned: transferResult.billedAccountReassigned,
          overageMigrated: transferResult.overageMigrated,
          billingBlockInherited: transferResult.billingBlockInherited,
        },
        request,
      })

      if (!alsoLeave) {
        return NextResponse.json({
          success: true,
          transferred: true,
          left: false,
          details: {
            workspacesReassigned: transferResult.workspacesReassigned,
            billedAccountReassigned: transferResult.billedAccountReassigned,
            overageMigrated: transferResult.overageMigrated,
            billingBlockInherited: transferResult.billingBlockInherited,
          },
        })
      }

      const [selfMember] = await db
        .select({ id: member.id })
        .from(member)
        .where(and(eq(member.organizationId, organizationId), eq(member.userId, session.user.id)))
        .limit(1)

      if (!selfMember) {
        return NextResponse.json({
          success: true,
          transferred: true,
          left: true,
          details: {
            workspacesReassigned: transferResult.workspacesReassigned,
            billedAccountReassigned: transferResult.billedAccountReassigned,
            overageMigrated: transferResult.overageMigrated,
            billingBlockInherited: transferResult.billingBlockInherited,
          },
        })
      }

      const removeResult = await removeUserFromOrganization({
        userId: session.user.id,
        organizationId,
        memberId: selfMember.id,
      })

      if (!removeResult.success) {
        logger.error('Transfer succeeded but self-removal failed', {
          organizationId,
          userId: session.user.id,
          error: removeResult.error,
        })
        return NextResponse.json(
          {
            success: true,
            transferred: true,
            left: false,
            warning: removeResult.error ?? 'Failed to leave after transfer',
          },
          { status: 207 }
        )
      }

      try {
        await setActiveOrganizationForCurrentSession(null)
      } catch (clearError) {
        logger.warn('Failed to clear active organization after transfer-and-leave', {
          userId: session.user.id,
          organizationId,
          error: clearError,
        })
      }

      recordAudit({
        workspaceId: null,
        actorId: session.user.id,
        actorName: session.user.name ?? undefined,
        actorEmail: session.user.email ?? undefined,
        action: AuditAction.ORG_MEMBER_REMOVED,
        resourceType: AuditResourceType.ORGANIZATION,
        resourceId: organizationId,
        description: 'Left the organization after transferring ownership',
        metadata: {
          targetUserId: session.user.id,
          wasSelfRemoval: true,
          followedOwnershipTransfer: true,
        },
        request,
      })

      return NextResponse.json({
        success: true,
        transferred: true,
        left: true,
        details: {
          workspacesReassigned: transferResult.workspacesReassigned,
          billedAccountReassigned: transferResult.billedAccountReassigned,
          overageMigrated: transferResult.overageMigrated,
          billingBlockInherited: transferResult.billingBlockInherited,
          billingActions: removeResult.billingActions,
        },
      })
    } catch (error) {
      logger.error('Failed to transfer organization ownership', {
        organizationId: (await context.params).id,
        error,
      })
      return NextResponse.json({ error: 'Failed to transfer ownership' }, { status: 500 })
    }
  }
)
