import { z } from 'zod';
import { db } from '../../db/db_index';
import { homeBanners } from '../../db/schema';
import { eq, and, desc, sql } from 'drizzle-orm';
import { protectedProcedure, router } from '../trpc-index';
import { extractKeyFromPresignedUrl, generateSignedUrlFromS3Url } from '../../lib/s3-client';
import { ApiError } from 'src/lib/api-error';
import { initializeAllStores } from '../../stores/store-initializer';

export const bannerRouter = router({
  // Get all banners
  getBanners: protectedProcedure
    .query(async () => {
      try {

      const banners = await db.query.homeBanners.findMany({
        orderBy: desc(homeBanners.createdAt), // Order by creation date instead
        // Removed product relationship since we now use productIds array
      });

      // Convert S3 keys to signed URLs for client
      const bannersWithSignedUrls = await Promise.all(
        banners.map(async (banner) => {
          try {
            return {
              ...banner,
              imageUrl: banner.imageUrl ? await generateSignedUrlFromS3Url(banner.imageUrl) : banner.imageUrl,
              // Ensure productIds is always an array
              productIds: banner.productIds || [],
            };
          } catch (error) {
            console.error(`Failed to generate signed URL for banner ${banner.id}:`, error);
            return {
              ...banner,
              imageUrl: banner.imageUrl, // Keep original on error
              // Ensure productIds is always an array
              productIds: banner.productIds || [],
            };
          }
        })
      );

      return {
        banners: bannersWithSignedUrls,
      };
      }
      catch(e:any) {
        console.log(e)
        
        throw new ApiError(e.message);
      }
    }),

  // Get single banner by ID
  getBanner: protectedProcedure
    .input(z.object({ id: z.number() }))
    .query(async ({ input }) => {
      const banner = await db.query.homeBanners.findFirst({
        where: eq(homeBanners.id, input.id),
        // Removed product relationship since we now use productIds array
      });

      if (banner) {
        try {
          // Convert S3 key to signed URL for client
          if (banner.imageUrl) {
            banner.imageUrl = await generateSignedUrlFromS3Url(banner.imageUrl);
          }
        } catch (error) {
          console.error(`Failed to generate signed URL for banner ${banner.id}:`, error);
          // Keep original imageUrl on error
        }

        // Ensure productIds is always an array (handle migration compatibility)
        if (!banner.productIds) {
          banner.productIds = [];
        }
      }

      return banner;
    }),

  // Create new banner
  createBanner: protectedProcedure
    .input(z.object({
      name: z.string().min(1),
      imageUrl: z.string().url(),
      description: z.string().optional(),
      productIds: z.array(z.number()).optional(),
      redirectUrl: z.string().url().optional(),
      // serialNum removed completely
    }))
    .mutation(async ({ input }) => {
      try {
        const imageUrl = extractKeyFromPresignedUrl(input.imageUrl)
        const [banner] = await db.insert(homeBanners).values({
          name: input.name,
          imageUrl: imageUrl,
          description: input.description,
          productIds: input.productIds || [],
          redirectUrl: input.redirectUrl,
          serialNum: 999, // Default value, not used
          isActive: false, // Default to inactive
        }).returning();

        // Reinitialize stores to reflect changes
        await initializeAllStores();

        return banner;
      } catch (error) {
        console.error('Error creating banner:', error);
        throw error; // Re-throw to maintain tRPC error handling
      }
    }),

  // Update banner
  updateBanner: protectedProcedure
    .input(z.object({
      id: z.number(),
      name: z.string().min(1).optional(),
      imageUrl: z.string().url().optional(),
      description: z.string().optional(),
      productIds: z.array(z.number()).optional(),
      redirectUrl: z.string().url().optional(),
      serialNum: z.number().nullable().optional(),
      isActive: z.boolean().optional(),
    }))
    .mutation(async ({ input }) => {
      try {
        
        const { id, ...updateData } = input;
        const incomingProductIds = input.productIds;
        // Extract S3 key from presigned URL if imageUrl is provided
        const processedData = {
          ...updateData,
          ...(updateData.imageUrl && {
            imageUrl: extractKeyFromPresignedUrl(updateData.imageUrl)
          }),
        };

        // Handle serialNum null case
        const finalData: any = { ...processedData };
        if ('serialNum' in finalData && finalData.serialNum === null) {
          // Set to null explicitly
          finalData.serialNum = null;
        }

        const [banner] = await db.update(homeBanners)
          .set({ ...finalData, lastUpdated: new Date(), })
          .where(eq(homeBanners.id, id))
          .returning();

        // Reinitialize stores to reflect changes
        await initializeAllStores();

        return banner;
      } catch (error) {
        console.error('Error updating banner:', error);
        throw error;
      }
    }),

  // Delete banner
  deleteBanner: protectedProcedure
    .input(z.object({ id: z.number() }))
    .mutation(async ({ input }) => {
      await db.delete(homeBanners).where(eq(homeBanners.id, input.id));

      // Reinitialize stores to reflect changes
      await initializeAllStores();

      return { success: true };
    }),
});