-- =====================================================================
-- Crowdlending Tracker - SQLite schema
-- =====================================================================
-- Conventions:
--   * Monetary amounts: REAL (cents-level precision OK for personal use)
--   * Dates: TEXT in ISO 8601 (YYYY-MM-DD) for stable sort & SQLite date()
--   * All tables use AUTOINCREMENT-free INTEGER PK (rowid alias)
--   * created_at/updated_at: TEXT ISO timestamp, set by app
-- =====================================================================

PRAGMA foreign_keys = ON;
PRAGMA journal_mode = WAL;

-- ---------------------------------------------------------------------
-- USERS  (login accounts)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS users (
  id              INTEGER PRIMARY KEY,
  email           TEXT NOT NULL UNIQUE,
  password_hash   TEXT NOT NULL,
  display_name    TEXT,
  created_at      TEXT NOT NULL DEFAULT (datetime('now')),
  updated_at      TEXT NOT NULL DEFAULT (datetime('now'))
);

-- ---------------------------------------------------------------------
-- INVESTISSEURS  (profils d'investissement sous un même login)
-- Ex.: "Monsieur", "Madame", "SCI Croguennec", "PEA-PME", ...
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS investisseurs (
  id              INTEGER PRIMARY KEY,
  user_id         INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  nom             TEXT NOT NULL,              -- nom complet (famille) ou raison sociale (entreprise)
  prenom          TEXT,                       -- prénom (famille uniquement)
  type            TEXT NOT NULL DEFAULT 'famille'
                  CHECK(type IN ('famille','entreprise')),
  type_fiscal     TEXT,                       -- 'PP', 'PM', 'SCI', 'SCPI'...
  notes           TEXT,
  created_at      TEXT NOT NULL DEFAULT (datetime('now')),
  updated_at      TEXT NOT NULL DEFAULT (datetime('now')),
  UNIQUE(user_id, nom)
);
CREATE INDEX IF NOT EXISTS idx_investisseurs_user ON investisseurs(user_id);

-- ---------------------------------------------------------------------
-- PLATEFORMES  (ClubFunding, October, Lendix, La Première Brique, ...)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS plateformes (
  id                    INTEGER PRIMARY KEY,
  user_id               INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  nom                   TEXT NOT NULL,
  url                   TEXT,
  notes                 TEXT,
  created_at            TEXT NOT NULL DEFAULT (datetime('now')),
  domiciliation         TEXT NOT NULL DEFAULT 'france',
  fiscalite             TEXT NOT NULL DEFAULT 'flat_tax',
  taux_fiscalite_locale REAL,
  methode_remboursement TEXT NOT NULL DEFAULT 'portefeuille',
  investisseur_id       INTEGER REFERENCES investisseurs(id) ON DELETE SET NULL,
  date_ouverture        TEXT,
  logo_filename         TEXT,
  UNIQUE(user_id, nom, investisseur_id)
);
CREATE INDEX IF NOT EXISTS idx_plateformes_user ON plateformes(user_id);

-- ---------------------------------------------------------------------
-- DEPOTS_RETRAITS  (mouvements de cash sur les plateformes)
-- type: 'depot' (versement)  |  'retrait' (retrait)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS depots_retraits (
  id              INTEGER PRIMARY KEY,
  investisseur_id INTEGER NOT NULL REFERENCES investisseurs(id) ON DELETE CASCADE,
  plateforme_id   INTEGER NOT NULL REFERENCES plateformes(id) ON DELETE RESTRICT,
  date_operation  TEXT NOT NULL,              -- ISO YYYY-MM-DD
  type            TEXT NOT NULL CHECK(type IN ('depot','retrait')),
  montant         REAL NOT NULL CHECK(montant >= 0),
  libelle         TEXT,
  reference       TEXT,                       -- ref bancaire / plateforme
  source          TEXT NOT NULL DEFAULT 'manuel',  -- 'manuel' | 'import_excel'
  notes           TEXT,
  created_at      TEXT NOT NULL DEFAULT (datetime('now')),
  updated_at      TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_depret_inv  ON depots_retraits(investisseur_id);
CREATE INDEX IF NOT EXISTS idx_depret_plat ON depots_retraits(plateforme_id);
CREATE INDEX IF NOT EXISTS idx_depret_date ON depots_retraits(date_operation);

-- ---------------------------------------------------------------------
-- INVESTISSEMENTS  (CF Investissements - liste des projets souscrits)
-- statut: 'en_cours' | 'rembourse' | 'en_retard' | 'procedure' | 'cloture'
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS investissements (
  id                 INTEGER PRIMARY KEY,
  investisseur_id    INTEGER NOT NULL REFERENCES investisseurs(id) ON DELETE CASCADE,
  plateforme_id      INTEGER NOT NULL REFERENCES plateformes(id) ON DELETE RESTRICT,
  nom_projet         TEXT NOT NULL,
  emetteur           TEXT,                    -- nom de la société emprunteuse
  date_souscription  TEXT NOT NULL,
  date_premiere_echeance TEXT,               -- date de la 1ère échéance (intérêts / remboursement)
  date_cible         TEXT,                    -- date contractuelle du dernier versement (calculée)
  montant_investi    REAL NOT NULL CHECK(montant_investi > 0),
  taux_interet       REAL,                    -- en % annuel (ex. 9.5)
  duree_mois         INTEGER,
  type_remb          TEXT,                    -- 'in_fine' | 'amortissable' | 'differe'
  freq_interets      TEXT NOT NULL DEFAULT 'mensuel', -- 'mensuel' | 'trimestriel' | 'in_fine'
  statut             TEXT NOT NULL DEFAULT 'en_cours'
                     CHECK(statut IN ('en_cours','rembourse','en_retard','procedure','cloture')),
  reference          TEXT,                    -- ID projet sur la plateforme
  source             TEXT NOT NULL DEFAULT 'manuel',
  notes              TEXT,
  created_at         TEXT NOT NULL DEFAULT (datetime('now')),
  updated_at         TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_inv_inv    ON investissements(investisseur_id);
CREATE INDEX IF NOT EXISTS idx_inv_plat   ON investissements(plateforme_id);
CREATE INDEX IF NOT EXISTS idx_inv_statut ON investissements(statut);
CREATE INDEX IF NOT EXISTS idx_inv_date   ON investissements(date_souscription);

-- ---------------------------------------------------------------------
-- REMBOURSEMENTS  (échéances perçues, réelles)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS remboursements (
  id                 INTEGER PRIMARY KEY,
  investissement_id  INTEGER NOT NULL REFERENCES investissements(id) ON DELETE CASCADE,
  date_remb          TEXT NOT NULL,
  capital            REAL NOT NULL DEFAULT 0,
  interets_bruts     REAL NOT NULL DEFAULT 0,    -- intérêts AVANT prélèvements
  prelev_sociaux     REAL NOT NULL DEFAULT 0,    -- 17.2 % typiquement
  prelev_forfaitaire REAL NOT NULL DEFAULT 0,    -- 12.8 % (PFU IR)
  cashback           REAL NOT NULL DEFAULT 0,    -- remboursement non taxé (bonus plateforme, etc.)
  interets_nets      REAL NOT NULL DEFAULT 0,    -- interets_bruts - prelev_sociaux - prelev_forfaitaire
  net_recu           REAL NOT NULL DEFAULT 0,    -- capital + cashback + interets_nets
  statut             TEXT NOT NULL DEFAULT 'paye'
                     CHECK(statut IN ('paye','retard','partiel','impaye')),
  source             TEXT NOT NULL DEFAULT 'manuel',
  notes              TEXT,
  created_at         TEXT NOT NULL DEFAULT (datetime('now')),
  updated_at         TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_remb_inv    ON remboursements(investissement_id);
CREATE INDEX IF NOT EXISTS idx_remb_date   ON remboursements(date_remb);
CREATE INDEX IF NOT EXISTS idx_remb_statut ON remboursements(statut);

-- ---------------------------------------------------------------------
-- SIMUL_REMBOURSEMENTS  (échéances prévisionnelles / théoriques)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS simul_remboursements (
  id                 INTEGER PRIMARY KEY,
  investissement_id  INTEGER NOT NULL REFERENCES investissements(id) ON DELETE CASCADE,
  numero_echeance    INTEGER NOT NULL,
  date_prevue        TEXT NOT NULL,
  capital_prevu      REAL NOT NULL DEFAULT 0,
  interets_prevus    REAL NOT NULL DEFAULT 0,
  total_prevu        REAL NOT NULL DEFAULT 0,
  notes              TEXT,
  created_at         TEXT NOT NULL DEFAULT (datetime('now')),
  UNIQUE(investissement_id, numero_echeance)
);
CREATE INDEX IF NOT EXISTS idx_simul_inv  ON simul_remboursements(investissement_id);
CREATE INDEX IF NOT EXISTS idx_simul_date ON simul_remboursements(date_prevue);

-- ---------------------------------------------------------------------
-- IMPORTS  (historique des imports Excel pour traçabilité)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS imports (
  id                 INTEGER PRIMARY KEY,
  user_id            INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  investisseur_id    INTEGER REFERENCES investisseurs(id) ON DELETE SET NULL,
  module             TEXT NOT NULL,           -- 'depots_retraits' | 'investissements' | ...
  filename           TEXT NOT NULL,
  rows_total         INTEGER NOT NULL DEFAULT 0,
  rows_inserted      INTEGER NOT NULL DEFAULT 0,
  rows_skipped       INTEGER NOT NULL DEFAULT 0,
  mapping_json       TEXT,                    -- JSON: mappage colonnes
  created_at         TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_imports_user ON imports(user_id);

-- ---------------------------------------------------------------------
-- CATEGORIES_PLATEFORME  (tags libres associés à une plateforme)
-- Semées par défaut à la première utilisation (voir route /categories)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS categories_plateforme (
  id         INTEGER PRIMARY KEY,
  user_id    INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  nom        TEXT NOT NULL,
  created_at TEXT NOT NULL DEFAULT (datetime('now')),
  UNIQUE(user_id, nom)
);
CREATE INDEX IF NOT EXISTS idx_catplat_user ON categories_plateforme(user_id);

-- Junction : une plateforme peut avoir plusieurs catégories
CREATE TABLE IF NOT EXISTS plateforme_categories (
  plateforme_id INTEGER NOT NULL REFERENCES plateformes(id) ON DELETE CASCADE,
  categorie_id  INTEGER NOT NULL REFERENCES categories_plateforme(id) ON DELETE CASCADE,
  PRIMARY KEY(plateforme_id, categorie_id)
);

-- ---------------------------------------------------------------------
-- TAUX_PFU  (historique Flat Tax France — table de référence globale)
-- ---------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS taux_pfu (
  id             INTEGER PRIMARY KEY,
  annee          INTEGER NOT NULL UNIQUE,
  pfu_total      REAL NOT NULL,          -- ex. 30.0
  impot_revenu   REAL NOT NULL,          -- ex. 12.8
  prelev_sociaux REAL NOT NULL,          -- ex. 17.2
  created_at     TEXT NOT NULL DEFAULT (datetime('now')),
  updated_at     TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_pfu_annee ON taux_pfu(annee);

-- ---------------------------------------------------------------------
-- VUES utiles
-- ---------------------------------------------------------------------

-- Solde courant par (investisseur, plateforme)
CREATE VIEW IF NOT EXISTS v_solde_plateforme AS
SELECT
  dr.investisseur_id,
  dr.plateforme_id,
  SUM(CASE WHEN dr.type='depot'   THEN dr.montant ELSE 0 END) AS total_depots,
  SUM(CASE WHEN dr.type='retrait' THEN dr.montant ELSE 0 END) AS total_retraits,
  SUM(CASE WHEN dr.type='depot'   THEN dr.montant
           WHEN dr.type='retrait' THEN -dr.montant END)        AS solde_net
FROM depots_retraits dr
GROUP BY dr.investisseur_id, dr.plateforme_id;

-- Synthèse investissements par investisseur
CREATE VIEW IF NOT EXISTS v_synthese_inv AS
SELECT
  i.investisseur_id,
  COUNT(*)                                                   AS nb_projets,
  SUM(i.montant_investi)                                     AS total_investi,
  SUM(CASE WHEN i.statut='en_cours'  THEN i.montant_investi ELSE 0 END) AS encours,
  SUM(CASE WHEN i.statut='rembourse' THEN i.montant_investi ELSE 0 END) AS rembourse,
  SUM(CASE WHEN i.statut IN ('en_retard','procedure') THEN i.montant_investi ELSE 0 END) AS en_defaut
FROM investissements i
GROUP BY i.investisseur_id;

-- Intérêts perçus par année (pour le 2778-SD)
CREATE VIEW IF NOT EXISTS v_interets_annuels AS
SELECT
  i.investisseur_id,
  substr(r.date_remb,1,4)                AS annee,
  SUM(r.interets_bruts)                  AS interets_bruts,
  SUM(r.prelev_sociaux)                  AS prelev_sociaux,
  SUM(r.prelev_forfaitaire)              AS prelev_forfaitaire,
  SUM(r.net_recu)                        AS net_recu
FROM remboursements r
JOIN investissements i ON i.id = r.investissement_id
WHERE r.statut IN ('paye','partiel')
GROUP BY i.investisseur_id, substr(r.date_remb,1,4);
