import { getVercelConnectionSettings, saveVercelConnectionSettings } from '~/lib/.server/connectionSettings';
import { createOrUpdateDeployment, getLatestDeployment } from '~/lib/.server/deployment';
import { createScopedLogger } from '~/lib/.server/logger';
import { DeploymentPlatformEnum, DeploymentStatusEnum } from '~/types/deployment';
import type { VercelProjectInfo } from '~/types/vercel';
import { errorResponse, successResponse } from '~/utils/api-response';
import { isBinaryString } from '~/utils/file-utils';

const logger = createScopedLogger('api.vercel.deploy');

export type GetVercelDeployByProjectIdArgs = {
  request: Request;
  userId: string;
};

export async function getVercelDeployByProjectId({ request, userId }: GetVercelDeployByProjectIdArgs) {
  const url = new URL(request.url);
  const projectId = url.searchParams.get('projectId');
  const requestToken = url.searchParams.get('token');

  // 从用户设置中获取连接信息
  let connectionSettings = await getVercelConnectionSettings(userId);

  // 如果请求参数中提供了token，优先使用请求参数中的信息，并更新用户设置
  if (requestToken) {
    connectionSettings = {
      token: requestToken,
    };

    // 更新用户设置
    await saveVercelConnectionSettings(userId, requestToken);
  }

  // 如果没有连接信息，返回错误
  if (!connectionSettings) {
    return errorResponse(401, '未连接到Vercel，请先设置访问令牌');
  }

  const { token } = connectionSettings;

  if (!projectId) {
    return errorResponse(400, '缺少项目ID');
  }

  try {
    // Get project info
    const projectResponse = await fetch(`https://api.vercel.com/v9/projects/${projectId}`, {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });

    if (!projectResponse.ok) {
      return errorResponse(400, '无法获取项目');
    }

    const projectData = (await projectResponse.json()) as any;

    // Get latest deployment
    const deploymentsResponse = await fetch(`https://api.vercel.com/v6/deployments?projectId=${projectId}&limit=1`, {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });

    if (!deploymentsResponse.ok) {
      return errorResponse(400, '获取部署信息失败');
    }

    const deploymentsData = (await deploymentsResponse.json()) as any;

    const latestDeployment = deploymentsData.deployments?.[0];

    return successResponse(
      {
        project: {
          id: projectData.id,
          name: projectData.name,
          url: `https://${projectData.name}.vercel.app`,
        },
        deploy: latestDeployment
          ? {
              id: latestDeployment.id,
              state: latestDeployment.state,
              url: latestDeployment.url ? `https://${latestDeployment.url}` : `https://${projectData.name}.vercel.app`,
            }
          : null,
      },
      '获取部署信息成功',
    );
  } catch (error) {
    logger.error('Error fetching Vercel deployment:', error);
    return errorResponse(500, '获取部署失败');
  }
}

interface DeployRequestBody {
  projectId?: string;
  files: Record<string, string>;
  chatId: string;
  token?: string;
}

export type HandleVercelDeployArgs = {
  request: Request;
  userId: string;
};

// Existing action function for POST requests
export async function handleVercelDeploy({ request, userId }: HandleVercelDeployArgs) {
  try {
    const { projectId, files, token: requestToken, chatId } = (await request.json()) as DeployRequestBody;

    // 从用户设置中获取连接信息
    let connectionSettings = await getVercelConnectionSettings(userId);

    // 如果请求体中提供了token，优先使用请求体中的信息，并更新用户设置
    if (requestToken) {
      connectionSettings = {
        token: requestToken,
      };

      // 更新用户设置
      await saveVercelConnectionSettings(userId, requestToken);
    }

    // 如果没有连接信息，返回错误
    if (!connectionSettings) {
      return errorResponse(401, '未连接到Vercel，请先设置访问令牌');
    }

    const { token } = connectionSettings;

    const existingDeployment = await getLatestDeployment(userId, chatId, DeploymentPlatformEnum.VERCEL);
    let targetProjectId;
    if (projectId) {
      targetProjectId = projectId;
    } else if (existingDeployment?.deploymentId) {
      targetProjectId = existingDeployment.deploymentId;
    } else {
      targetProjectId = undefined;
    }

    let projectInfo: VercelProjectInfo | undefined;

    if (targetProjectId) {
      const projectResponse = await fetch(`https://api.vercel.com/v9/projects/${targetProjectId}`, {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      });

      if (projectResponse.ok) {
        const existingProject = (await projectResponse.json()) as any;
        projectInfo = {
          id: existingProject.id,
          name: existingProject.name,
          url: `https://${existingProject.name}.vercel.app`,
          chatId,
        };
      }
    }

    if (!projectInfo) {
      const projectName = `upage-${chatId}-${Date.now()}`.toLocaleLowerCase();
      const createProjectResponse = await fetch('https://api.vercel.com/v9/projects', {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${token}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          name: projectName,
          framework: null,
        }),
      });

      if (!createProjectResponse.ok) {
        const errorData = (await createProjectResponse.json()) as any;
        return errorResponse(400, `创建项目失败: ${errorData.error?.message || '未知错误'}`);
      }

      const newProject = (await createProjectResponse.json()) as any;
      targetProjectId = newProject.id;
      projectInfo = {
        id: newProject.id,
        name: newProject.name,
        url: `https://${newProject.name}.vercel.app`,
        chatId,
      };
    }

    // Prepare files for deployment
    const deploymentFiles = [];

    for (const [filePath, content] of Object.entries(files)) {
      // Ensure file path doesn't start with a slash for Vercel
      const normalizedPath = filePath.startsWith('/') ? filePath.substring(1) : filePath;
      deploymentFiles.push({
        file: normalizedPath,
        data: isBinaryString(content) ? Buffer.from(content, 'binary').toString('base64') : content,
        encoding: isBinaryString(content) ? 'base64' : 'utf-8',
      });
    }

    // Create a new deployment
    const deployResponse = await fetch(`https://api.vercel.com/v13/deployments`, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        name: projectInfo.name,
        project: targetProjectId,
        target: 'production',
        files: deploymentFiles,
        routes: [{ src: '/(.*)', dest: '/$1' }],
      }),
    });

    if (!deployResponse.ok) {
      const errorData = (await deployResponse.json()) as any;
      return errorResponse(400, `创建部署失败: ${errorData.error?.message || '未知错误'}`);
    }

    const deployData = (await deployResponse.json()) as any;

    // Poll for deployment status
    let retryCount = 0;
    const maxRetries = 60;
    let deploymentUrl = '';
    let deploymentState = '';

    while (retryCount < maxRetries) {
      const statusResponse = await fetch(`https://api.vercel.com/v13/deployments/${deployData.id}`, {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      });

      if (statusResponse.ok) {
        const status = (await statusResponse.json()) as any;
        deploymentState = status.readyState;
        const alias = status.alias;
        const automaticAliases = status.automaticAliases;

        if (status.readyState === 'READY' || status.readyState === 'ERROR') {
          if (status.aliasAssigned) {
            const diffAlias = alias.filter((item: string) => !automaticAliases.includes(item));
            deploymentUrl = `https://${diffAlias[0]}`;
          } else {
            deploymentUrl = status.url ? `https://${status.url}` : '';
          }
          break;
        }
      }

      retryCount++;
      await new Promise((resolve) => setTimeout(resolve, 2000));
    }

    if (deploymentState === 'ERROR') {
      return errorResponse(500, '部署失败');
    }

    if (retryCount >= maxRetries) {
      return errorResponse(500, '部署超时');
    }

    const finalUrl = deploymentUrl || projectInfo.url;

    // 记录部署信息
    try {
      await createOrUpdateDeployment({
        userId,
        chatId,
        platform: DeploymentPlatformEnum.VERCEL,
        deploymentId: deployData.id,
        url: finalUrl,
        status: deploymentState === 'READY' ? DeploymentStatusEnum.SUCCESS : DeploymentStatusEnum.PENDING,
        metadata: {
          projectId: projectInfo.id,
          projectName: projectInfo.name,
        },
      });
      logger.info(`为用户 ${userId} 创建了 Vercel 部署记录`);
    } catch (error) {
      logger.error('创建部署记录失败:', error);
      // 不影响主流程，继续返回成功
    }

    return successResponse(
      {
        deploy: {
          id: deployData.id,
          state: deploymentState,
          url: finalUrl,
        },
        project: projectInfo,
      },
      '部署成功',
    );
  } catch (error) {
    logger.error('Vercel deploy error:', error);
    return errorResponse(500, '部署失败');
  }
}
