import { TEXT_MESSAGES } from "../const";
import db from "../db";

export interface ProductInput {
  productName: string;
  productImage?: string;
  description?: string;
  assetClass?: string;
  minimumInvestment?: number;
  investorType?: string;
}

export interface Asset {
  id: number;
  market: string;
  numberOfInvestments: number;
  benchmark?: string;
  inceptionDate?: string;
  products?: ProductInput[];
}

export interface AssetInput {
  market: string;
  numberOfInvestments: number;
  benchmark: string;
  inceptionDate: string;
  products: ProductInput[];
}

export class AssetModel {
  static async initialize() {
    try {
      await db.query(`
        CREATE TABLE IF NOT EXISTS assets (
          id INT AUTO_INCREMENT PRIMARY KEY,
          market VARCHAR(255) NOT NULL,
          number_of_investments INT NOT NULL,
          benchmark VARCHAR(255),
          inception_date DATE
        )
      `);

      await db.query(`
        CREATE TABLE IF NOT EXISTS asset_products (
          id INT AUTO_INCREMENT PRIMARY KEY,
          asset_id INT,
          product_name VARCHAR(255),
          product_image TEXT,
          description TEXT,
          asset_class VARCHAR(100),
          minimum_investment FLOAT,
          investor_type VARCHAR(100),
          FOREIGN KEY (asset_id) REFERENCES assets(id) ON DELETE CASCADE
        )
      `);

      console.info(TEXT_MESSAGES.ASSETS_AND_ASSETPRODUCTS_TABLES_INITIALIZED);
    } catch (error) {
      console.error(TEXT_MESSAGES.FAILED_TO_INTIALIZE, error);
    }
  }

  static async createAsset(assetData: AssetInput) {
    const { market, numberOfInvestments, benchmark, inceptionDate, products } =
      assetData;

    const [result]: any = await db.query(
      `INSERT INTO assets (market, number_of_investments, benchmark, inception_date) VALUES (?, ?, ?, ?)`,
      [market, numberOfInvestments, benchmark, inceptionDate]
    );

    const assetId: number = result.insertId;

    const insertedProducts = [];

    for (const product of products) {
      const [productResult]: any = await db.query(
        `INSERT INTO asset_products (asset_id, product_name, product_image, description, asset_class, minimum_investment, investor_type) VALUES (?, ?, ?, ?, ?, ?, ?)`,
        [
          assetId,
          product.productName,
          product.productImage || null,
          product.description || null,
          product.assetClass || null,
          product.minimumInvestment || 0,
          product.investorType || null,
        ]
      );

      insertedProducts.push({
        id: productResult.insertId,
        ...product,
      });
    }

    return {
      id: assetId,
      market,
      numberOfInvestments,
      benchmark,
      inceptionDate,
      products: insertedProducts,
    };
  }

  static async findAllAssets() {
    const [assets]: any = await db.query("SELECT * FROM assets");

    const formattedAssets = await Promise.all(
      assets.map(async (asset: any) => {
        const [products]: any = await db.query(
          `SELECT * FROM asset_products WHERE asset_id = ?`,
          [asset.id]
        );

        const formattedProducts = products.map((product: any) => ({
          id: product.id,
          productName: product.product_name ?? "Untitled Product",
          productImage: product.product_image || null,
          description: product.description || null,
          assetClass: product.asset_class || null,
          minimumInvestment: product.minimum_investment || 0,
          investorType: product.investor_type || null,
        }));

        return {
          id: asset.id,
          market: asset.market,
          numberOfInvestments: asset.number_of_investments ?? 0,
          benchmark: asset.benchmark,
          inceptionDate: asset.inception_date,
          products: formattedProducts,
        };
      })
    );

    return formattedAssets;
  }

static async getAssetById(id: number) {
  const [assets]: any = await db.query(
    `SELECT * FROM assets WHERE id = ?`,
    [id]
  );

  if (!assets || assets.length === 0) return null;

  const asset = assets[0];

  const [products]: any = await db.query(
    `SELECT * FROM asset_products WHERE asset_id = ?`,
    [id]
  );

  const formattedProducts = products.map((product: any) => ({
    id: product.id,
    productName: product.product_name,
    productImage: product.product_image || null,
    description: product.description || null,
    assetClass: product.asset_class || null,
    minimumInvestment: product.minimum_investment || 0,
    investorType: product.investor_type || null,
  }));

  return {
    id: asset.id,
    market: asset.market,
    numberOfInvestments: asset.number_of_investments ?? 0,
    benchmark: asset.benchmark,
    inceptionDate: asset.inception_date,
    products: formattedProducts,
  };
}
}

(async function bootstrapAssets() {
  await AssetModel.initialize();
  console.info(TEXT_MESSAGES.ASSETS_AND_ASSETPRODUCTS_TABLES_MIGRATED);
})();
