import { router, protectedProcedure, adminProcedure } from '../_core/trpc.ts';
import { z } from 'zod';
import { TRPCError } from '@trpc/server';
import {
  createReportCustomization,
  updateReportCustomization,
  validateCustomization,
  cloneCustomization,
  createFromTemplate,
  customizationTemplates,
  type ReportCustomization,
} from '../reportCustomization.ts';

/**
 * Report Scheduling Router
 * Manage custom report configurations, scheduling, and execution
 */

// Validation schemas
const reportCustomizationSchema = z.object({
  name: z.string().min(1).max(100),
  type: z.enum(['payment', 'reconciliation', 'fraud', 'withdrawal', 'analytics']),
  dateRange: z.object({
    type: z.enum(['predefined', 'custom']),
    predefined: z.enum(['7d', '30d', '90d', 'ytd', 'all']).optional(),
    customStart: z.date().optional(),
    customEnd: z.date().optional(),
  }),
  metrics: z.record(z.array(z.string())).optional(),
  filters: z.record(z.array(z.string())).optional(),
  recipients: z.object({
    emails: z.array(z.string().email()),
    includeOwner: z.boolean().optional(),
  }),
  delivery: z.object({
    frequency: z.enum(['once', 'daily', 'weekly', 'monthly']),
    time: z.string().optional(),
    format: z.enum(['html', 'pdf', 'csv', 'json']),
  }),
  enabled: z.boolean().optional(),
});

export const reportSchedulingRouter = router({
  /**
   * Create a new custom report configuration
   */
  create: adminProcedure
    .input(reportCustomizationSchema)
    .mutation(async ({ input, ctx }) => {
      try {
        const customization = createReportCustomization(
          `REPORT-${Date.now()}`,
          input.name,
          input.type
        );

        // Update with provided values
        const updated = updateReportCustomization(customization, {
          dateRange: input.dateRange,
          recipients: input.recipients,
          delivery: input.delivery,
          metrics: input.metrics,
          filters: input.filters,
        });

        // Validate
        const validation = validateCustomization(updated);
        if (!validation.valid) {
          throw new TRPCError({
            code: 'BAD_REQUEST',
            message: validation.errors.join(', '),
          });
        }

        // In production, save to database
        console.log('[Report Scheduling] Created report:', updated.id);

        return {
          success: true,
          customization: updated,
          message: 'Report configuration created successfully',
        };
      } catch (error) {
        console.error('[Report Scheduling] Error creating report:', error);
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to create report configuration',
        });
      }
    }),

  /**
   * Get all custom report configurations
   */
  list: adminProcedure.query(async ({ ctx }) => {
    try {
      // In production, fetch from database
      const mockConfigurations: ReportCustomization[] = [];

      return {
        success: true,
        configurations: mockConfigurations,
        total: mockConfigurations.length,
      };
    } catch (error) {
      console.error('[Report Scheduling] Error listing reports:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to fetch report configurations',
      });
    }
  }),

  /**
   * Get a specific report configuration
   */
  get: adminProcedure
    .input(z.object({ id: z.string() }))
    .query(async ({ input, ctx }) => {
      try {
        // In production, fetch from database
        const customization = createReportCustomization(input.id, 'Sample Report', 'payment');

        return {
          success: true,
          customization,
        };
      } catch (error) {
        console.error('[Report Scheduling] Error fetching report:', error);
        throw new TRPCError({
          code: 'NOT_FOUND',
          message: 'Report configuration not found',
        });
      }
    }),

  /**
   * Update a report configuration
   */
  update: adminProcedure
    .input(
      z.object({
        id: z.string(),
        updates: reportCustomizationSchema.partial(),
      })
    )
    .mutation(async ({ input, ctx }) => {
      try {
        // In production, fetch from database
        let customization = createReportCustomization(input.id, 'Sample Report', 'payment');

        // Apply updates
        customization = updateReportCustomization(customization, input.updates);

        // Validate
        const validation = validateCustomization(customization);
        if (!validation.valid) {
          throw new TRPCError({
            code: 'BAD_REQUEST',
            message: validation.errors.join(', '),
          });
        }

        // In production, save to database
        console.log('[Report Scheduling] Updated report:', customization.id);

        return {
          success: true,
          customization,
          message: 'Report configuration updated successfully',
        };
      } catch (error) {
        console.error('[Report Scheduling] Error updating report:', error);
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to update report configuration',
        });
      }
    }),

  /**
   * Delete a report configuration
   */
  delete: adminProcedure
    .input(z.object({ id: z.string() }))
    .mutation(async ({ input, ctx }) => {
      try {
        // In production, delete from database
        console.log('[Report Scheduling] Deleted report:', input.id);

        return {
          success: true,
          message: 'Report configuration deleted successfully',
        };
      } catch (error) {
        console.error('[Report Scheduling] Error deleting report:', error);
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to delete report configuration',
        });
      }
    }),

  /**
   * Clone a report configuration
   */
  clone: adminProcedure
    .input(
      z.object({
        id: z.string(),
        newName: z.string(),
      })
    )
    .mutation(async ({ input, ctx }) => {
      try {
        // In production, fetch from database
        let customization = createReportCustomization(input.id, 'Sample Report', 'payment');
        const cloned = cloneCustomization(customization, input.newName);

        // In production, save to database
        console.log('[Report Scheduling] Cloned report:', cloned.id);

        return {
          success: true,
          customization: cloned,
          message: 'Report configuration cloned successfully',
        };
      } catch (error) {
        console.error('[Report Scheduling] Error cloning report:', error);
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to clone report configuration',
        });
      }
    }),

  /**
   * Create report from template
   */
  createFromTemplate: adminProcedure
    .input(
      z.object({
        template: z.enum(['paymentDaily', 'reconciliationWeekly', 'fraudMonthly', 'withdrawalWeekly']),
      })
    )
    .mutation(async ({ input, ctx }) => {
      try {
        const customization = createFromTemplate(
          input.template as keyof typeof customizationTemplates,
          `REPORT-${Date.now()}`
        );

        // In production, save to database
        console.log('[Report Scheduling] Created report from template:', customization.id);

        return {
          success: true,
          customization,
          message: 'Report created from template successfully',
        };
      } catch (error) {
        console.error('[Report Scheduling] Error creating from template:', error);
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to create report from template',
        });
      }
    }),

  /**
   * Enable/disable a report configuration
   */
  toggle: adminProcedure
    .input(
      z.object({
        id: z.string(),
        enabled: z.boolean(),
      })
    )
    .mutation(async ({ input, ctx }) => {
      try {
        // In production, update in database
        console.log('[Report Scheduling] Toggled report:', input.id, 'enabled:', input.enabled);

        return {
          success: true,
          message: `Report ${input.enabled ? 'enabled' : 'disabled'} successfully`,
        };
      } catch (error) {
        console.error('[Report Scheduling] Error toggling report:', error);
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to toggle report',
        });
      }
    }),

  /**
   * Add recipient to report
   */
  addRecipient: adminProcedure
    .input(
      z.object({
        id: z.string(),
        email: z.string().email(),
      })
    )
    .mutation(async ({ input, ctx }) => {
      try {
        // In production, fetch and update in database
        console.log('[Report Scheduling] Added recipient to report:', input.id, input.email);

        return {
          success: true,
          message: 'Recipient added successfully',
        };
      } catch (error) {
        console.error('[Report Scheduling] Error adding recipient:', error);
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to add recipient',
        });
      }
    }),

  /**
   * Remove recipient from report
   */
  removeRecipient: adminProcedure
    .input(
      z.object({
        id: z.string(),
        email: z.string().email(),
      })
    )
    .mutation(async ({ input, ctx }) => {
      try {
        // In production, fetch and update in database
        console.log('[Report Scheduling] Removed recipient from report:', input.id, input.email);

        return {
          success: true,
          message: 'Recipient removed successfully',
        };
      } catch (error) {
        console.error('[Report Scheduling] Error removing recipient:', error);
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to remove recipient',
        });
      }
    }),

  /**
   * Get report templates
   */
  getTemplates: adminProcedure.query(async ({ ctx }) => {
    try {
      const templates = Object.entries(customizationTemplates).map(([key, template]) => ({
        key,
        name: template.name,
        type: template.type,
        frequency: template.delivery.frequency,
        description: `${template.type} report - ${template.delivery.frequency}`,
      }));

      return {
        success: true,
        templates,
      };
    } catch (error) {
      console.error('[Report Scheduling] Error fetching templates:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to fetch templates',
      });
    }
  }),

  /**
   * Get report execution history
   */
  getExecutionHistory: adminProcedure
    .input(
      z.object({
        id: z.string(),
        limit: z.number().optional().default(20),
      })
    )
    .query(async ({ input, ctx }) => {
      try {
        // In production, fetch from database
        const history = [
          {
            id: 'EXEC-1',
            reportId: input.id,
            executedAt: new Date(),
            status: 'success',
            recipientCount: 5,
            deliveryTime: 2.5,
          },
          {
            id: 'EXEC-2',
            reportId: input.id,
            executedAt: new Date(Date.now() - 86400000),
            status: 'success',
            recipientCount: 5,
            deliveryTime: 2.3,
          },
        ];

        return {
          success: true,
          history: history.slice(0, input.limit),
          total: history.length,
        };
      } catch (error) {
        console.error('[Report Scheduling] Error fetching execution history:', error);
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to fetch execution history',
        });
      }
    }),

  /**
   * Execute report immediately
   */
  executeNow: adminProcedure
    .input(z.object({ id: z.string() }))
    .mutation(async ({ input, ctx }) => {
      try {
        // In production, trigger report generation and email delivery
        console.log('[Report Scheduling] Executing report immediately:', input.id);

        return {
          success: true,
          message: 'Report execution started',
          executionId: `EXEC-${Date.now()}`,
        };
      } catch (error) {
        console.error('[Report Scheduling] Error executing report:', error);
        throw new TRPCError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Failed to execute report',
        });
      }
    }),

  /**
   * Get report statistics
   */
  getStats: adminProcedure.query(async ({ ctx }) => {
    try {
      // In production, fetch from database
      return {
        success: true,
        stats: {
          totalReports: 12,
          enabledReports: 10,
          disabledReports: 2,
          totalExecutions: 156,
          successfulExecutions: 154,
          failedExecutions: 2,
          averageExecutionTime: 2.4,
          nextScheduledExecution: new Date(Date.now() + 3600000),
        },
      };
    } catch (error) {
      console.error('[Report Scheduling] Error fetching stats:', error);
      throw new TRPCError({
        code: 'INTERNAL_SERVER_ERROR',
        message: 'Failed to fetch statistics',
      });
    }
  }),
});
