/**
 * Workflow Management Service
 * Handles business logic for user workflows with tier-based feature gating
 */

import { userWorkflowsAdapter } from '@/lib/adapters/workflows';
import {
  WorkflowType,
  WorkflowStatus,
  UserWorkflow,
  CreateWorkflowRequest,
  WorkflowWithPermissions,
  WorkflowActivationResult,
  TierWorkflowMapping,
} from '@/lib/types/workflow.types';

/**
 * Tier-based workflow access mapping
 * Each tier includes all workflows from lower tiers
 */
const TIER_WORKFLOW_MAP: Record<string, WorkflowType[]> = {
  tier1: ['ai_agent', 'whatsapp', 'appointments'],
  tier2: ['ai_agent', 'whatsapp', 'appointments', 'quotations', 'crm', 'integrations', 'deposits'],
  tier3: [
    'ai_agent',
    'whatsapp',
    'appointments',
    'quotations',
    'crm',
    'integrations',
    'deposits',
    'voice_agent',
    'multi_staff',
    'recurring',
  ],
  tier4: [
    'ai_agent',
    'whatsapp',
    'appointments',
    'quotations',
    'crm',
    'integrations',
    'deposits',
    'voice_agent',
    'multi_staff',
    'recurring',
    'social_media',
    'ai_social',
  ],
  tier5: [
    'ai_agent',
    'whatsapp',
    'appointments',
    'quotations',
    'crm',
    'integrations',
    'deposits',
    'voice_agent',
    'multi_staff',
    'recurring',
    'social_media',
    'ai_social',
    'lead_generation',
    'lead_scoring',
  ],
};

/**
 * Display names for tiers (for upgrade prompts)
 */
const TIER_NAMES: Record<string, string> = {
  tier1: 'Starter',
  tier2: 'Professional',
  tier3: 'Business',
  tier4: 'Enterprise',
  tier5: 'Ultimate',
};

/**
 * Find the minimum tier required for a workflow type
 */
function getRequiredTierForWorkflow(workflowType: WorkflowType): string | null {
  for (const [tier, workflows] of Object.entries(TIER_WORKFLOW_MAP)) {
    if (workflows.includes(workflowType)) {
      return tier;
    }
  }
  return null;
}

/**
 * Check if a tier has access to a workflow type
 */
function hasWorkflowAccess(tier: string, workflowType: WorkflowType): boolean {
  const allowedWorkflows = TIER_WORKFLOW_MAP[tier] || [];
  return allowedWorkflows.includes(workflowType);
}

export class WorkflowManagementService {
  /**
   * Get all allowed workflow types for a specific tier
   */
  static getAllowedWorkflowsByTier(tier: string): WorkflowType[] {
    return TIER_WORKFLOW_MAP[tier] || [];
  }

  /**
   * Get all tier workflow mappings
   */
  static getTierMappings(): TierWorkflowMapping[] {
    return Object.entries(TIER_WORKFLOW_MAP).map(([tier, workflows]) => ({
      tier,
      workflows,
      displayName: TIER_NAMES[tier] || tier,
    }));
  }

  /**
   * Get all workflows for a user with permission flags based on their package tier
   */
  static async getUserWorkflows(
    userId: string,
    packageTier: string
  ): Promise<WorkflowWithPermissions[]> {
    const workflows = await userWorkflowsAdapter.findMany({
      where: { userId },
      orderBy: { createdAt: 'desc' },
    });

    const allowedWorkflows = this.getAllowedWorkflowsByTier(packageTier);

    return workflows.map((workflow) => {
      const canActivate = allowedWorkflows.includes(workflow.workflowType as WorkflowType);
      const requiresUpgrade = !canActivate;
      const upgradeTier = requiresUpgrade
        ? getRequiredTierForWorkflow(workflow.workflowType as WorkflowType)
        : undefined;

      return {
        ...workflow,
        config: workflow.config as Record<string, any>,
        status: workflow.status as WorkflowStatus,
        canActivate,
        canConfigure: canActivate, // Can only configure workflows they can activate
        requiresUpgrade,
        upgradeTier: upgradeTier ? TIER_NAMES[upgradeTier] : undefined,
      };
    });
  }

  /**
   * Get a single workflow by ID
   */
  static async getWorkflowById(workflowId: string, userId: string): Promise<UserWorkflow | null> {
    const workflow = await userWorkflowsAdapter.findFirst({
      where: {
        id: workflowId,
        userId,
      },
    });

    if (!workflow) {
      return null;
    }

    return {
      ...workflow,
      config: workflow.config as Record<string, any>,
      status: workflow.status as WorkflowStatus,
    };
  }

  /**
   * Create a new workflow (always starts as inactive)
   */
  static async createWorkflow(
    userId: string,
    data: CreateWorkflowRequest
  ): Promise<UserWorkflow> {
    // Check if workflow already exists for this user
    const existingWorkflow = await userWorkflowsAdapter.findFirst({
      where: {
        userId,
        workflowType: data.workflowType,
      },
    });

    if (existingWorkflow) {
      throw new Error(`Workflow of type ${data.workflowType} already exists for this user`);
    }

    const workflowData = {
      userId,
      workflowType: data.workflowType,
      n8nWorkflowId: data.n8nWorkflowId,
      status: 'inactive' as const,
      config: data.config,
      lastRunStatus: null,
    };

    // Save to both databases

    return {
      ...workflow,
      config: workflow.config as Record<string, any>,
      status: workflow.status as WorkflowStatus,
    };
  }

  /**
   * Activate a workflow (with tier-based access check)
   */
  static async activateWorkflow(
    workflowId: string,
    userId: string,
    packageTier: string
  ): Promise<WorkflowActivationResult> {
    // Get the workflow
    const workflow = await userWorkflowsAdapter.findFirst({
      where: {
        id: workflowId,
        userId,
      },
    });

    if (!workflow) {
      throw new Error('Workflow not found or unauthorized');
    }

    // Check if user's tier has access to this workflow type
    const workflowType = workflow.workflowType as WorkflowType;
    if (!hasWorkflowAccess(packageTier, workflowType)) {
      const requiredTier = getRequiredTierForWorkflow(workflowType);
      const tierName = requiredTier ? TIER_NAMES[requiredTier] : 'higher';
      throw new Error(
        `Workflow type ${workflowType} requires ${tierName} tier or higher. Please upgrade your plan.`
      );
    }

    // Update workflow status to active
    const updatedWorkflow = await prisma.userWorkflow.update({
      where: { id: workflowId },
      data: { status: 'active' },
    });

    return {
      success: true,
      workflowId: updatedWorkflow.id,
      status: 'active',
      message: 'Workflow activated successfully',
    };
  }

  /**
   * Deactivate a workflow
   */
  static async deactivateWorkflow(
    workflowId: string,
    userId: string
  ): Promise<WorkflowActivationResult> {
    // Verify ownership
    const workflow = await userWorkflowsAdapter.findFirst({
      where: {
        id: workflowId,
        userId,
      },
    });

    if (!workflow) {
      throw new Error('Workflow not found or unauthorized');
    }

    // Update workflow status to inactive

    return {
      success: true,
      workflowId: updatedWorkflow.id,
      status: 'inactive',
      message: 'Workflow deactivated successfully',
    };
  }

  /**
   * Update workflow configuration
   */
  static async updateWorkflowConfig(
    workflowId: string,
    userId: string,
    config: Record<string, any>
  ): Promise<UserWorkflow> {
    // Verify ownership
    const workflow = await userWorkflowsAdapter.findFirst({
      where: {
        id: workflowId,
        userId,
      },
    });

    if (!workflow) {
      throw new Error('Workflow not found or unauthorized');
    }

    // Update workflow configuration

    return {
      ...updatedWorkflow,
      config: updatedWorkflow.config as Record<string, any>,
      status: updatedWorkflow.status as WorkflowStatus,
    };
  }

  /**
   * Delete a workflow
   */
  static async deleteWorkflow(workflowId: string, userId: string): Promise<void> {
    // Verify ownership
    const workflow = await userWorkflowsAdapter.findFirst({
      where: {
        id: workflowId,
        userId,
      },
    });

    if (!workflow) {
      throw new Error('Workflow not found or unauthorized');
    }

    // Delete from both databases
  }

  /**
   * Update workflow run status (called by n8n webhook)
   */
  static async updateWorkflowRunStatus(
    workflowId: string,
    status: string,
    runAt: Date = new Date()
  ): Promise<void> {
  }

  /**
   * Get workflow statistics for a user
   */
  static async getWorkflowStats(userId: string): Promise<{
    total: number;
    active: number;
    inactive: number;
    error: number;
  }> {
    const workflows = await userWorkflowsAdapter.findMany({
      where: { userId },
      select: { status: true },
    });

    return {
      total: workflows.length,
      active: workflows.filter((w) => w.status === 'active').length,
      inactive: workflows.filter((w) => w.status === 'inactive').length,
      error: workflows.filter((w) => w.status === 'error').length,
    };
  }
}
