import db from '../config/database';
import { DomainEventBus } from '../core/runtime/DomainEventBus';
import { logger } from '../utils/logger';

export interface WebsiteTemplate {
  id: string;
  tenantId: string;
  name: string;
  category: 'ecommerce' | 'blog' | 'portfolio' | 'landing';
  layout: Record<string, any>;
  styles: Record<string, any>;
  components: string[];
  status: 'draft' | 'published';
  createdAt: Date;
}

export interface PageConfig {
  id: string;
  websiteId: string;
  name: string;
  path: string;
  components: PageComponent[];
  seoConfig: Record<string, any>;
  createdAt: Date;
}

export interface PageComponent {
  id: string;
  type: string;
  props: Record<string, any>;
  position: { x: number; y: number; w: number; h: number };
}

export interface BrandConfig {
  id: string;
  tenantId: string;
  name: string;
  logo?: string;
  colors: Record<string, string>;
  fonts: Record<string, string>;
  story?: string;
  values: string[];
  createdAt: Date;
}

export interface MultilingualConfig {
  id: string;
  websiteId: string;
  defaultLanguage: string;
  supportedLanguages: string[];
  translations: Record<string, Record<string, string>>;
  createdAt: Date;
}

export class StoreCreationService {
  private static TEMPLATE_TABLE = 'cf_website_template';
  private static PAGE_TABLE = 'cf_page_config';
  private static BRAND_TABLE = 'cf_brand_config';
  private static LANG_TABLE = 'cf_multilingual_config';

  static async initTables(): Promise<void> {
    await this.initTemplateTable();
    await this.initPageTable();
    await this.initBrandTable();
    await this.initLangTable();
  }

  private static async initTemplateTable(): Promise<void> {
    const hasTable = await db.schema.hasTable(this.TEMPLATE_TABLE);
    if (!hasTable) {
      logger.info(`[StoreCreation] Creating ${this.TEMPLATE_TABLE} table...`);
      await db.schema.createTable(this.TEMPLATE_TABLE, (table) => {
        table.string('id', 36).primary();
        table.string('tenant_id', 36).notNullable().index();
        table.string('name', 128).notNullable();
        table.enum('category', ['ecommerce', 'blog', 'portfolio', 'landing']).notNullable();
        table.json('layout');
        table.json('styles');
        table.json('components');
        table.enum('status', ['draft', 'published']).defaultTo('draft');
        table.datetime('created_at').notNullable().defaultTo(db.fn.now());
      });
      logger.info(`[StoreCreation] Table ${this.TEMPLATE_TABLE} created`);
    }
  }

  private static async initPageTable(): Promise<void> {
    const hasTable = await db.schema.hasTable(this.PAGE_TABLE);
    if (!hasTable) {
      logger.info(`[StoreCreation] Creating ${this.PAGE_TABLE} table...`);
      await db.schema.createTable(this.PAGE_TABLE, (table) => {
        table.string('id', 36).primary();
        table.string('website_id', 36).notNullable().index();
        table.string('name', 128).notNullable();
        table.string('path', 256).notNullable();
        table.json('components');
        table.json('seo_config');
        table.datetime('created_at').notNullable().defaultTo(db.fn.now());
        table.unique(['website_id', 'path'], 'uk_website_path');
      });
      logger.info(`[StoreCreation] Table ${this.PAGE_TABLE} created`);
    }
  }

  private static async initBrandTable(): Promise<void> {
    const hasTable = await db.schema.hasTable(this.BRAND_TABLE);
    if (!hasTable) {
      logger.info(`[StoreCreation] Creating ${this.BRAND_TABLE} table...`);
      await db.schema.createTable(this.BRAND_TABLE, (table) => {
        table.string('id', 36).primary();
        table.string('tenant_id', 36).notNullable().index();
        table.string('name', 128).notNullable();
        table.string('logo', 512);
        table.json('colors');
        table.json('fonts');
        table.text('story');
        table.json('values');
        table.datetime('created_at').notNullable().defaultTo(db.fn.now());
      });
      logger.info(`[StoreCreation] Table ${this.BRAND_TABLE} created`);
    }
  }

  private static async initLangTable(): Promise<void> {
    const hasTable = await db.schema.hasTable(this.LANG_TABLE);
    if (!hasTable) {
      logger.info(`[StoreCreation] Creating ${this.LANG_TABLE} table...`);
      await db.schema.createTable(this.LANG_TABLE, (table) => {
        table.string('id', 36).primary();
        table.string('website_id', 36).notNullable().index();
        table.string('default_language', 5).notNullable();
        table.json('supported_languages');
        table.json('translations');
        table.datetime('created_at').notNullable().defaultTo(db.fn.now());
      });
      logger.info(`[StoreCreation] Table ${this.LANG_TABLE} created`);
    }
  }

  static async createTemplate(
    tenantId: string,
    params: { name: string; category: string; designParams: Record<string, any> }
  ): Promise<WebsiteTemplate> {
    const id = this.generateId();
    const template: WebsiteTemplate = {
      id,
      tenantId,
      name: params.name,
      category: params.category as WebsiteTemplate['category'],
      layout: params.designParams.layout || {},
      styles: params.designParams.styles || {},
      components: params.designParams.components || [],
      status: 'draft',
      createdAt: new Date(),
    };

    await db(this.TEMPLATE_TABLE).insert({
      id: template.id,
      tenant_id: template.tenantId,
      name: template.name,
      category: template.category,
      layout: JSON.stringify(template.layout),
      styles: JSON.stringify(template.styles),
      components: JSON.stringify(template.components),
      status: template.status,
      created_at: template.createdAt,
    });

    logger.info(`[StoreCreation] Created template ${id}`);
    return template;
  }

  static async updatePageComponents(
    websiteId: string,
    pageId: string,
    components: PageComponent[]
  ): Promise<PageConfig> {
    const existing = await db(this.PAGE_TABLE)
      .where({ website_id: websiteId, id: pageId })
      .first();

    const pageData = {
      id: existing?.id || pageId,
      website_id: websiteId,
      name: existing?.name || 'New Page',
      path: existing?.path || '/new-page',
      components: JSON.stringify(components),
      seo_config: existing?.seo_config || JSON.stringify({}),
      created_at: existing?.created_at || new Date(),
    };

    if (existing) {
      await db(this.PAGE_TABLE)
        .where({ id: existing.id })
        .update({ components: JSON.stringify(components) });
    } else {
      await db(this.PAGE_TABLE).insert(pageData);
    }

    logger.info(`[StoreCreation] Updated page ${pageId} with ${components.length} components`);
    return {
      id: pageData.id,
      websiteId: pageData.website_id,
      name: pageData.name,
      path: pageData.path,
      components,
      seoConfig: JSON.parse(pageData.seo_config),
      createdAt: pageData.created_at,
    };
  }

  static async adaptResponsiveLayout(
    websiteId: string,
    pageId: string,
    deviceType: 'desktop' | 'tablet' | 'mobile'
  ): Promise<PageComponent[]> {
    const page = await db(this.PAGE_TABLE)
      .where({ website_id: websiteId, id: pageId })
      .first();

    if (!page) {
      throw new Error(`Page ${pageId} not found`);
    }

    const components: PageComponent[] = JSON.parse(page.components);
    const scaleFactor: Record<string, number> = {
      desktop: 1,
      tablet: 0.75,
      mobile: 0.5,
    };

    const scale = scaleFactor[deviceType];
    const adapted = components.map((comp) => ({
      ...comp,
      position: {
        x: Math.round(comp.position.x * scale),
        y: Math.round(comp.position.y * scale),
        w: Math.round(comp.position.w * scale),
        h: Math.round(comp.position.h * scale),
      },
    }));

    logger.info(`[StoreCreation] Adapted layout for ${deviceType}`);
    return adapted;
  }

  static async setupMultilingual(
    websiteId: string,
    languages: string[]
  ): Promise<MultilingualConfig> {
    const id = this.generateId();
    const config: MultilingualConfig = {
      id,
      websiteId,
      defaultLanguage: languages[0] || 'en',
      supportedLanguages: languages,
      translations: {},
      createdAt: new Date(),
    };

    await db(this.LANG_TABLE).insert({
      id: config.id,
      website_id: config.websiteId,
      default_language: config.defaultLanguage,
      supported_languages: JSON.stringify(config.supportedLanguages),
      translations: JSON.stringify(config.translations),
      created_at: config.createdAt,
    });

    logger.info(`[StoreCreation] Setup multilingual for website ${websiteId}`);
    return config;
  }

  static async createBrand(
    tenantId: string,
    params: { name: string; designAssets: Record<string, any> }
  ): Promise<BrandConfig> {
    const id = this.generateId();
    const brand: BrandConfig = {
      id,
      tenantId,
      name: params.name,
      logo: params.designAssets.logo,
      colors: params.designAssets.colors || {},
      fonts: params.designAssets.fonts || {},
      story: params.designAssets.story,
      values: params.designAssets.values || [],
      createdAt: new Date(),
    };

    await db(this.BRAND_TABLE).insert({
      id: brand.id,
      tenant_id: brand.tenantId,
      name: brand.name,
      logo: brand.logo,
      colors: JSON.stringify(brand.colors),
      fonts: JSON.stringify(brand.fonts),
      story: brand.story,
      values: JSON.stringify(brand.values),
      created_at: brand.createdAt,
    });

    await DomainEventBus.publish({
      type: 'brand.created',
      tenantId,
      data: { brandId: id, name: params.name },
      timestamp: new Date(),
    });

    logger.info(`[StoreCreation] Created brand ${id}`);
    return brand;
  }

  static async manageContent(
    brandId: string,
    contentData: { type: string; content: string }
  ): Promise<{ success: boolean; message: string }> {
    await db(this.BRAND_TABLE)
      .where({ id: brandId })
      .update({ story: contentData.content });

    logger.info(`[StoreCreation] Updated content for brand ${brandId}`);
    return { success: true, message: 'Content updated' };
  }

  static async integrateEcommerce(
    websiteId: string,
    features: string[]
  ): Promise<{ success: boolean; config: Record<string, any> }> {
    const config: Record<string, any> = {};

    for (const feature of features) {
      config[feature] = { enabled: true, settings: {} };
    }

    await DomainEventBus.publish({
      type: 'website.ecommerce.integrated',
      tenantId: websiteId,
      data: { websiteId, features },
      timestamp: new Date(),
    });

    logger.info(`[StoreCreation] Integrated ecommerce features: ${features.join(', ')}`);
    return { success: true, config };
  }

  static async integrateMarketing(
    websiteId: string,
    params: Record<string, any>
  ): Promise<{ success: boolean; config: Record<string, any> }> {
    const config = {
      emailMarketing: params.emailMarketing || false,
      socialMedia: params.socialMedia || [],
      seo: params.seo || {},
    };

    logger.info(`[StoreCreation] Integrated marketing tools for website ${websiteId}`);
    return { success: true, config };
  }

  static async configureShipping(
    websiteId: string,
    params: Record<string, any>
  ): Promise<{ success: boolean; config: Record<string, any> }> {
    const config = {
      carriers: params.carriers || [],
      zones: params.zones || [],
      rates: params.rates || {},
    };

    logger.info(`[StoreCreation] Configured shipping for website ${websiteId}`);
    return { success: true, config };
  }

  static async generateAnalytics(
    websiteId: string,
    params: { metrics: string[]; timeRange: { start: Date; end: Date } }
  ): Promise<Record<string, any>> {
    const report: Record<string, any> = {};

    for (const metric of params.metrics) {
      report[metric] = {
        value: Math.floor(Math.random() * 10000),
        trend: Math.random() > 0.5 ? 'up' : 'down',
        change: `${(Math.random() * 20 - 10).toFixed(1)}%`,
      };
    }

    logger.info(`[StoreCreation] Generated analytics report for website ${websiteId}`);
    return report;
  }

  static async optimizeSEO(
    websiteId: string,
    params: Record<string, any>
  ): Promise<{ success: boolean; suggestions: string[] }> {
    const suggestions = [
      'Add meta description to homepage',
      'Optimize image alt texts',
      'Improve page load speed',
      'Add structured data markup',
    ];

    await db(this.PAGE_TABLE)
      .where({ website_id: websiteId })
      .update({ seo_config: JSON.stringify(params) });

    logger.info(`[StoreCreation] Optimized SEO for website ${websiteId}`);
    return { success: true, suggestions };
  }

  static async integrateSocialMedia(
    websiteId: string,
    accounts: Array<{ platform: string; accountId: string }>
  ): Promise<{ success: boolean; config: Record<string, any> }> {
    const config: Record<string, any> = {};

    for (const account of accounts) {
      config[account.platform] = { accountId: account.accountId, connected: true };
    }

    logger.info(`[StoreCreation] Integrated social media for website ${websiteId}`);
    return { success: true, config };
  }

  static async manageContentMarketing(
    websiteId: string,
    contentData: Record<string, any>
  ): Promise<{ success: boolean; contentId: string }> {
    const contentId = this.generateId();

    logger.info(`[StoreCreation] Created content marketing item ${contentId}`);
    return { success: true, contentId };
  }

  static async spreadBrandStory(
    brandId: string,
    params: { channels: string[]; schedule?: Date }
  ): Promise<{ success: boolean; reach: number }> {
    const reach = Math.floor(Math.random() * 100000) + 1000;

    await DomainEventBus.publish({
      type: 'brand.story.spread',
      tenantId: brandId,
      data: { brandId, channels: params.channels, reach },
      timestamp: new Date(),
    });

    logger.info(`[StoreCreation] Spread brand story for brand ${brandId}`);
    return { success: true, reach };
  }

  private static generateId(): string {
    return `sc_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }
}
