-- Unify asset categories onto item_categories / item_subcategories
-- Run against PostgreSQL before deploying BE that expects item_* FKs on assets.
--
-- Pre-check (optional):
--   SELECT ac.code, ac.name AS asset_cat, ic.name AS item_cat
--   FROM asset_categories ac
--   JOIN item_categories ic ON UPPER(ac.code) = UPPER(ic.code)
--    AND ac.deleted_at IS NULL AND ic.deleted_at IS NULL;

BEGIN;

-- =========================================================
-- 1) Extend item_categories with asset defaults
-- =========================================================
ALTER TABLE item_categories
  ADD COLUMN IF NOT EXISTS code_prefix VARCHAR(10),
  ADD COLUMN IF NOT EXISTS default_useful_life_years INT,
  ADD COLUMN IF NOT EXISTS default_depreciation_method VARCHAR(20);

DO $$
BEGIN
  IF NOT EXISTS (
    SELECT 1 FROM pg_constraint WHERE conname = 'item_categories_code_prefix_key'
  ) THEN
    ALTER TABLE item_categories
      ADD CONSTRAINT item_categories_code_prefix_key UNIQUE (code_prefix);
  END IF;
END $$;

-- =========================================================
-- 2) Mapping tables
-- =========================================================
CREATE TEMP TABLE map_asset_category (
  old_asset_category_id BIGINT PRIMARY KEY,
  new_item_category_id  BIGINT NOT NULL
);

CREATE TEMP TABLE map_asset_subcategory (
  old_asset_subcategory_id BIGINT PRIMARY KEY,
  new_item_subcategory_id  BIGINT NOT NULL
);

-- =========================================================
-- 3) Upsert asset_categories -> item_categories
-- =========================================================
WITH src AS (
  SELECT *
  FROM asset_categories
  WHERE deleted_at IS NULL
),
matched AS (
  SELECT s.id AS old_id, ic.id AS new_id
  FROM src s
  JOIN item_categories ic
    ON UPPER(ic.code) = UPPER(s.code)
   AND ic.deleted_at IS NULL
),
inserted AS (
  INSERT INTO item_categories (
    code, name, code_prefix,
    default_useful_life_years, default_depreciation_method,
    is_active, created_by, updated_by, created_at, updated_at
  )
  SELECT
    s.code,
    s.name,
    s.code_prefix,
    s.default_useful_life_years,
    s.default_depreciation_method,
    s.is_active,
    s.created_by,
    s.updated_by,
    s.created_at,
    s.updated_at
  FROM src s
  WHERE NOT EXISTS (
    SELECT 1 FROM matched m WHERE m.old_id = s.id
  )
  RETURNING id, code
)
INSERT INTO map_asset_category (old_asset_category_id, new_item_category_id)
SELECT old_id, new_id FROM matched
UNION ALL
SELECT s.id, i.id
FROM src s
JOIN inserted i ON UPPER(i.code) = UPPER(s.code);

UPDATE item_categories ic
SET
  code_prefix = COALESCE(ic.code_prefix, ac.code_prefix),
  default_useful_life_years = COALESCE(ic.default_useful_life_years, ac.default_useful_life_years),
  default_depreciation_method = COALESCE(ic.default_depreciation_method, ac.default_depreciation_method),
  updated_at = NOW()
FROM asset_categories ac
JOIN map_asset_category m ON m.old_asset_category_id = ac.id
WHERE ic.id = m.new_item_category_id
  AND ac.deleted_at IS NULL;

-- =========================================================
-- 4) Upsert asset_subcategories -> item_subcategories
-- =========================================================
WITH src AS (
  SELECT asub.*, m.new_item_category_id
  FROM asset_subcategories asub
  JOIN map_asset_category m ON m.old_asset_category_id = asub.asset_category_id
  WHERE asub.deleted_at IS NULL
),
matched AS (
  SELECT s.id AS old_id, isub.id AS new_id
  FROM src s
  JOIN item_subcategories isub
    ON UPPER(isub.code) = UPPER(s.code)
   AND isub.deleted_at IS NULL
),
inserted AS (
  INSERT INTO item_subcategories (
    item_category_id, code, name,
    is_active, created_by, updated_by, created_at, updated_at
  )
  SELECT
    s.new_item_category_id,
    s.code,
    s.name,
    s.is_active,
    s.created_by,
    s.updated_by,
    s.created_at,
    s.updated_at
  FROM src s
  WHERE NOT EXISTS (
    SELECT 1 FROM matched m WHERE m.old_id = s.id
  )
  RETURNING id, code
)
INSERT INTO map_asset_subcategory (old_asset_subcategory_id, new_item_subcategory_id)
SELECT old_id, new_id FROM matched
UNION ALL
SELECT s.id, i.id
FROM src s
JOIN inserted i ON UPPER(i.code) = UPPER(s.code);

UPDATE item_subcategories isub
SET
  item_category_id = mcat.new_item_category_id,
  updated_at = NOW()
FROM map_asset_subcategory msub
JOIN asset_subcategories asub ON asub.id = msub.old_asset_subcategory_id
JOIN map_asset_category mcat ON mcat.old_asset_category_id = asub.asset_category_id
WHERE isub.id = msub.new_item_subcategory_id;

-- =========================================================
-- 5) Remap assets to item_* columns
-- =========================================================
ALTER TABLE assets
  ADD COLUMN IF NOT EXISTS item_category_id BIGINT,
  ADD COLUMN IF NOT EXISTS item_subcategory_id BIGINT;

UPDATE assets a
SET
  item_category_id = mapped.new_item_category_id,
  item_subcategory_id = mapped.new_item_subcategory_id,
  updated_at = NOW()
FROM (
  SELECT
    a2.id AS asset_id,
    mcat.new_item_category_id,
    msub.new_item_subcategory_id
  FROM assets a2
  JOIN map_asset_category mcat
    ON mcat.old_asset_category_id = a2.asset_category_id
  LEFT JOIN map_asset_subcategory msub
    ON msub.old_asset_subcategory_id = a2.asset_subcategory_id
) mapped
WHERE a.id = mapped.asset_id;

DO $$
DECLARE missing_count BIGINT;
BEGIN
  SELECT COUNT(*) INTO missing_count
  FROM assets
  WHERE deleted_at IS NULL
    AND item_category_id IS NULL;

  IF missing_count > 0 THEN
    RAISE EXCEPTION '% active assets could not be mapped to item_category_id', missing_count;
  END IF;
END $$;

ALTER TABLE assets
  ALTER COLUMN item_category_id SET NOT NULL;

DO $$
BEGIN
  IF NOT EXISTS (
    SELECT 1 FROM pg_constraint WHERE conname = 'assets_item_category_id_fkey'
  ) THEN
    ALTER TABLE assets
      ADD CONSTRAINT assets_item_category_id_fkey
      FOREIGN KEY (item_category_id) REFERENCES item_categories (id);
  END IF;

  IF NOT EXISTS (
    SELECT 1 FROM pg_constraint WHERE conname = 'assets_item_subcategory_id_fkey'
  ) THEN
    ALTER TABLE assets
      ADD CONSTRAINT assets_item_subcategory_id_fkey
      FOREIGN KEY (item_subcategory_id) REFERENCES item_subcategories (id);
  END IF;
END $$;

CREATE INDEX IF NOT EXISTS idx_assets_item_category_id ON assets (item_category_id);
CREATE INDEX IF NOT EXISTS idx_assets_item_subcategory_id ON assets (item_subcategory_id);

-- =========================================================
-- 6) Drop dependent views, then old asset category FKs / columns / tables
-- =========================================================
DROP VIEW IF EXISTS v_asset_expiry_alerts CASCADE;
DROP VIEW IF EXISTS v_asset_next_service CASCADE;
DROP VIEW IF EXISTS v_assets CASCADE;

ALTER TABLE assets DROP CONSTRAINT IF EXISTS assets_asset_category_id_fkey;
ALTER TABLE assets DROP CONSTRAINT IF EXISTS assets_asset_subcategory_id_fkey;
DROP INDEX IF EXISTS idx_assets_category_id;
DROP INDEX IF EXISTS idx_assets_subcategory_id;
ALTER TABLE assets DROP COLUMN IF EXISTS asset_category_id;
ALTER TABLE assets DROP COLUMN IF EXISTS asset_subcategory_id;

DROP TABLE IF EXISTS asset_subcategories;
DROP TABLE IF EXISTS asset_categories;

COMMIT;

-- Recreate reporting views after this script:
--   psql ... -f scripts/patch-assets-views.sql
