import 'package:weblibre/data/database/converters/color.dart';
import 'package:weblibre/data/database/converters/uri.dart';
import 'package:weblibre/features/geckoview/features/tabs/data/models/container_data.dart';
import 'package:weblibre/features/geckoview/features/tabs/data/models/tab_query_result.dart';
import 'package:weblibre/features/geckoview/features/tabs/data/database/converters/container_metadata_converter.dart';

CREATE TABLE container (
  id TEXT PRIMARY KEY NOT NULL,
  name TEXT,
  color INTEGER NOT NULL MAPPED BY `const ColorConverter()`,
  metadata TEXT MAPPED BY `const ContainerMetadataConverter()`
) WITH ContainerData;

CREATE TABLE tab ( 
  id TEXT PRIMARY KEY NOT NULL,
  container_id TEXT REFERENCES container (id) ON DELETE CASCADE,
  order_key TEXT NOT NULL,
  url TEXT MAPPED BY `const UriConverter()`,
  title TEXT,
  is_probably_readerable BOOL,
  extracted_content_markdown TEXT,
  extracted_content_plain TEXT,
  full_content_markdown TEXT,
  full_content_plain TEXT,
  timestamp DATETIME NOT NULL
);

import '../../features/vector_store/data/database/vector_store.drift'; 

-- automativcally remove documents and embeddings on delete
-- isnert and updates are managed code side
CREATE TRIGGER tab_document_delete AFTER DELETE ON tab BEGIN
  DELETE FROM document WHERE main_document_id = old.id;
END;

CREATE VIRTUAL TABLE tab_fts 
  USING fts5(
    title,
    url,
    extracted_content_plain,
    full_content_plain,
    content=tab,
    tokenize="trigram"
  );

-- Triggers to keep the FTS index up to date.
CREATE TRIGGER tab_after_insert AFTER INSERT ON tab BEGIN
  INSERT INTO 
    tab_fts(rowid, title, url, extracted_content_plain, full_content_plain) 
    VALUES (new.rowid, new.title, new.url, new.extracted_content_plain, new.full_content_plain);
END;
CREATE TRIGGER tab_after_delete AFTER DELETE ON tab BEGIN
  INSERT INTO 
    tab_fts(tab_fts, rowid, title, url, extracted_content_plain, full_content_plain) 
    VALUES('delete', old.rowid, old.title, old.url, old.extracted_content_plain, old.full_content_plain);
END;
CREATE TRIGGER tab_after_update AFTER UPDATE ON tab BEGIN
  INSERT INTO 
    tab_fts(tab_fts, rowid, title, url, extracted_content_plain, full_content_plain) 
    VALUES('delete', old.rowid, old.title, old.url, old.extracted_content_plain, old.full_content_plain);
  INSERT INTO 
    tab_fts(rowid, title, url, extracted_content_plain, full_content_plain) 
    VALUES (new.rowid, new.title, new.url, new.extracted_content_plain, new.full_content_plain);
END;

optimizeFtsIndex:
  INSERT INTO tab_fts(tab_fts) VALUES ('optimize');

containersWithCount WITH ContainerDataWithCount:
  SELECT 
    container.*, 
    tab_agg.tab_count
  FROM container
  LEFT JOIN (
    SELECT 
      container_id, 
      COUNT(*) AS tab_count, 
      MAX(timestamp) AS last_updated
    FROM tab
    GROUP BY container_id
  ) AS tab_agg ON container.id = tab_agg.container_id
  ORDER BY tab_agg.last_updated DESC NULLS LAST;

leadingOrderKey(:container_id AS TEXT OR NULL, :bucket AS INTEGER):
  SELECT lexo_rank_previous(
    :bucket, 
    (
      SELECT order_key 
      FROM tab 
      WHERE container_id IS :container_id 
      ORDER BY order_key 
      LIMIT 1
    )
  );

trailingOrderKey(:container_id AS TEXT OR NULL, :bucket AS INTEGER):
  SELECT lexo_rank_next(
    :bucket, 
    (
      SELECT order_key 
      FROM tab 
      WHERE container_id IS :container_id 
      ORDER BY order_key DESC 
      LIMIT 1
    )
  );

orderKeyAfterTab(:tab_id AS TEXT, :container_id AS TEXT OR NULL):
  WITH ordered_table AS (
    SELECT id,
          order_key,
          LEAD(order_key) OVER (ORDER BY order_key) AS next_order_key
    FROM tab 
    WHERE container_id IS :container_id 
  )
  SELECT lexo_rank_reorder_after(order_key, next_order_key)
  FROM ordered_table
  WHERE id = :tab_id;

queryTabsBasic WITH TabQueryResult:
  WITH weights AS (
    SELECT 
      -- Customize these weights (higher = more important)
      10.0 as title_weight,       -- Title matches are most important
      5.0 as url_weight           -- URL matches are quite important
  )
  SELECT 
    t.id,
    t.title,
    CAST(t.url AS TEXT) AS url,
    t.url AS clean_url,
    bm25(tab_fts, weights.title_weight, weights.url_weight) AS weighted_rank
  FROM tab_fts fts
  INNER JOIN
    tab t ON t.rowid = fts.rowid 
  CROSS JOIN weights
  WHERE 
  	fts.title LIKE :query OR
  	fts.url LIKE :query
  ORDER BY 
  	weighted_rank ASC,
  	t.timestamp DESC;

queryTabsFullContent WITH TabQueryResult:
  WITH weights AS (
  SELECT 
    -- Customize these weights (higher = more important)
    10.0 as title_weight,     -- Title matches are most important
    5.0 as url_weight,        -- URL matches are quite important
    3.0 as extracted_weight,  -- Extracted content matches
    1.0 as full_weight       -- Full content matches less important
  )
  SELECT 
      t.id,
      highlight(tab_fts, 0, :beforeMatch, :afterMatch) AS title,
      highlight(tab_fts, 1, :beforeMatch, :afterMatch) AS url,
      snippet(tab_fts, 2, :beforeMatch, :afterMatch, :ellipsis, :snippetLength) AS extracted_content,
      snippet(tab_fts, 3, :beforeMatch, :afterMatch, :ellipsis, :snippetLength) AS full_content,
      t.url AS clean_url,
      (
        bm25(tab_fts, weights.title_weight, weights.url_weight, 
            weights.extracted_weight, weights.full_weight)
      ) AS weighted_rank
    FROM tab_fts(:query) fts
    INNER JOIN
      tab t ON t.rowid = fts.rowid
    CROSS JOIN weights
    ORDER BY 
      weighted_rank ASC,
      t.timestamp DESC;