import { Request, Response } from 'express';
import catchAsync from '@/shared/utils/catchAsync';
import { myOperatorService } from './myoperator.service';
import { maskApiToken, maskMyOperatorCredentials } from '@/shared/utils/maskingHelper';
import httpStatus from 'http-status';
import User from '@/modules/user/user.model';

/**
 * Save MyOperator credentials
 * POST /api/v1/myoperator/credentials
 */
export const saveCredentials = catchAsync(
  async (req: Request, res: Response) => {
    const companyId = req.user.company.id;
    const { apiToken, secretKey, xApiKey, companyId: myOperatorCompanyId, webhookSecret, publicIvrId, isActive } = req.body;

    const result = await myOperatorService.saveCredentials(companyId, {
      apiToken,
      secretKey,
      xApiKey,
      companyId: myOperatorCompanyId,
      webhookSecret,
      publicIvrId,
      isActive,
    });

    const statusCode = result.success ? 200 : 207;
    const message = result.success 
      ? 'MyOperator credentials saved and connection tested successfully'
      : `MyOperator credentials saved but connection failed: ${result.message}`;

    res.success({
      isActive,
      maskedToken: maskApiToken(apiToken),
      maskedSecretKey: secretKey ? maskApiToken(secretKey) : undefined,
      maskedXApiKey: xApiKey ? maskApiToken(xApiKey) : undefined,
      maskedWebhookSecret: webhookSecret ? maskApiToken(webhookSecret) : undefined,
      companyId: maskApiToken(myOperatorCompanyId),
      publicIvrId: maskApiToken(publicIvrId),
      connectionStatus: result.connectionStatus,
    }, statusCode, message);
  },
);

/**
 * Get MyOperator credentials (masked)
 * GET /api/v1/myoperator/credentials
 */
export const getCredentials = catchAsync(
  async (req: Request, res: Response) => {
    const companyId = req.user.company.id;

    const { Company } = await import('@/modules/company/company.model');
    const company = await Company.findById(companyId).select('myoperator');

    if (!company?.myoperator) {
      return res.success({
        configured: false,
        active: false,
        connectionStatus: 'disconnected',
      }, 200, 'MyOperator not configured');
    }

    const myoperator = company.myoperator;

    const maskedCredentials = maskMyOperatorCredentials(myoperator);

    res.success({
      configured: Boolean(myoperator.apiToken),
      ...maskedCredentials,
    }, 200, 'MyOperator credentials retrieved');
  },
);

/**
 * Test MyOperator connection
 * POST /api/v1/myoperator/credentials/test
 */
export const testConnection = catchAsync(
  async (req: Request, res: Response) => {
    const companyId = req.user.company.id;

    const result = await myOperatorService.testConnection(companyId);

    res.success({
      status: result.status,
    }, result.success ? 200 : 400, result.message);
  },
);

/**
 * Deactivate MyOperator integration
 * DELETE /api/v1/myoperator/credentials
 */
export const deactivateIntegration = catchAsync(
  async (req: Request, res: Response) => {
    const companyId = req.user.company.id;

    await myOperatorService.deactivate(companyId);

    res.success(null, 200, 'MyOperator integration deactivated');
  },
);

/**
 * Sync a single user to MyOperator
 * POST /api/v1/myoperator/users/sync
 */
export const syncUser = catchAsync(async (req: Request, res: Response) => {
  const companyId = req.user.company.id;
  const { userId, extension } = req.body;

  const result = await myOperatorService.syncUser({
    userId,
    companyId,
    extension,
  });

  if (!result.success) {
    return res.status(httpStatus.BAD_REQUEST).json({
      success: false,
      message: result.error || 'Failed to sync user',
    });
  }

  res.success({
    uuid: result.uuid,
    extension: result.extension,
  }, 200, result.message || 'User synced successfully');
});


/**
 * List MyOperator users
 * GET /api/v1/myoperator/users
 */
export const listUsers = catchAsync(async (req: Request, res: Response) => {
  const companyId = req.user.company.id;
  const { keyword, page, pageSize, all } = req.query;

  const users = await myOperatorService.listUsers(companyId, {
    keyword: keyword as string,
    page: page ? parseInt(page as string) : undefined,
    pageSize: pageSize ? parseInt(pageSize as string) : undefined,
    all: all === 'true',
  });

  res.success({
    users,
    count: users.length,
  }, 200, 'Users retrieved successfully');
});

/**
 * Update MyOperator user
 * PUT /api/v1/myoperator/users/:userId
 */
export const updateUser = catchAsync(async (req: Request, res: Response) => {
  const companyId = req.user.company.id;
  const { userId } = req.params;
  const user = await User.findById(userId).select('myoperator');

  if (!user?.myoperator?.uuid) {
    return res.status(httpStatus.BAD_REQUEST).json({
      success: false,
      message: 'User is not synced with MyOperator',
    });
  }

  const updatePayload = {
    uuid: user.myoperator.uuid,
    ...req.body,
  };

  await myOperatorService.updateUser(companyId, updatePayload);

  res.success(null, 200, 'User updated successfully in MyOperator');
});

export const deleteUser = catchAsync(async (req: Request, res: Response) => {
  const companyId = req.user.company.id;
  const { userId } = req.params;
  const user = await User.findById(userId).select('myoperator');

  if (!user?.myoperator?.uuid) {
    return res.status(httpStatus.BAD_REQUEST).json({
      success: false,
      message: 'User is not synced with MyOperator',
    });
  }

  const { uuid } = await myOperatorService.deleteUser(companyId, user.myoperator.uuid);

  await User.findByIdAndUpdate(userId, {
    $unset: { myoperator: 1 },
  });

  res.success({ uuid }, 200, 'User removed successfully from MyOperator');
});

/**
 * Search call logs
 * GET /api/v1/myoperator/call/logs
 */
export const searchCallLogs = catchAsync(
  async (req: Request, res: Response) => {
    const companyId = req.user.company.id;
    const { from, to, logFrom, pageSize, searchKey, filters } = req.query;

    const logs = await myOperatorService.searchCallLogs(companyId, {
      from: from ? parseInt(from as string) : undefined,
      to: to ? parseInt(to as string) : undefined,
      logFrom: logFrom ? parseInt(logFrom as string) : undefined,
      pageSize: pageSize ? parseInt(pageSize as string) : undefined,
      searchKey: searchKey as string,
      filters: filters as string,
    });

    res.success({
      logs,
      count: logs.length,
    }, 200, 'Call logs retrieved successfully');
  },
);

/**
 * Get log filters
 * GET /api/v1/myoperator/call/filters
 */
export const getLogFilters = catchAsync(
  async (req: Request, res: Response) => {
    const companyId = req.user.company.id;

    const filters = await myOperatorService.getLogFilters(companyId);

    res.success({
      filters,
    }, 200, 'Filters retrieved successfully');
  },
);

  /**
   * Get recording link
   * GET /api/v1/myoperator/call/recording/:filename
   */
  export const getRecordingLink = catchAsync(
    async (req: Request, res: Response) => {
      const companyId = req.user.company.id;
      const { filename } = req.params;

      const recording = await myOperatorService.getRecordingLink(
        companyId,
        String(filename),
      );

      res.success(recording, 200, 'Recording link retrieved successfully');
    },
  );

  export const initiateClickToCall = catchAsync(
    async (req: Request, res: Response) => {
      const companyId = req.user.company.id;
      const { userId, contactId, leadId } = req.body;

      try {
        const result = await myOperatorService.initiateClickToCall(
          companyId,
          {
            userId,
            contactId,
            leadId
          },
        );

        res.success({
          uniqueId: result.uniqueId,
          referenceId: result.referenceId,
        }, result.success ? 200 : 400, result.message);
      } catch (error: any) {
        res.status(httpStatus.BAD_REQUEST).json({
          success: false,
          message: error.message || 'Failed to initiate call',
        });
      }
    },
  );

  export const getCallStatus = catchAsync(
    async (req: Request, res: Response) => {
      const companyId = req.user.company.id;
      const { userId } = req.query;

      const result = await myOperatorService.getCallStatus(companyId, {
        userId: userId as string,
      });

      res.success(result, 200, result.ongoing ? 'Call is ongoing' : 'No ongoing call');
    },
  );

  export const submitFeatureRequest = catchAsync(
    async (req: Request, res: Response) => {
      const companyId = req.user.company.id;
      const { firstName, lastName, email, phone, companyName } = req.body;

      const result = await myOperatorService.submitFeatureRequest(
        companyId,
        {
          firstName,
          lastName,
          email,
          phone,
          companyName,
        },
      );

      res.success(result, 201, 'Request submitted successfully. Admin will contact you via email with credentials.');
    },
  );
