-- =============================================
-- NETGESCON: SISTEMA CONTABILE COMPLETO v3.0
-- Partita Doppia + Multi-Gestione + Protocolli + Maschera Unica + Riconciliazione Avanzata
-- =============================================

-- FEATURES AGGIORNATE:
-- ✅ Maschera Unica di Registrazione per tutti i documenti
-- ✅ Tabelle Millesimali Strutturate con calcoli automatici
-- ✅ Riconciliazione Bancaria con algoritmi di matching
-- ✅ Triggers per aggiornamento saldi real-time
-- ✅ Sistema Backup Granulari per singolo condominio
-- ✅ Compliance Fiscale automatica
-- ✅ Workflow guidato step-by-step
-- ✅ Audit completo con tracciabilità totale

-- 1. PIANO DEI CONTI (3 LIVELLI: MASTRO.CONTO.SOTTOCONTO)
CREATE TABLE piano_conti (
    id INT PRIMARY KEY AUTO_INCREMENT,
    condominio_id INT NOT NULL,
    codice VARCHAR(10) NOT NULL COMMENT 'Formato: 01.001.0001',
    mastro VARCHAR(2) NOT NULL COMMENT 'Primo livello: 01, 02, 03...',
    conto VARCHAR(3) NOT NULL COMMENT 'Secondo livello: 001, 002, 003...',
    sottoconto VARCHAR(4) NOT NULL COMMENT 'Terzo livello: 0001, 0002, 0003...',
    denominazione VARCHAR(255) NOT NULL,
    tipo_conto ENUM('ATTIVO','PASSIVO','COSTO','RICAVO','PATRIMONIALE') NOT NULL,
    natura ENUM('DARE','AVERE') NOT NULL COMMENT 'Natura contabile del conto',
    gestione ENUM('TUTTE','ORDINARIA','RISCALDAMENTO','STRAORDINARIA') DEFAULT 'TUTTE',
    attivo BOOLEAN DEFAULT TRUE,
    saldo_dare DECIMAL(12,2) DEFAULT 0.00,
    saldo_avere DECIMAL(12,2) DEFAULT 0.00,
    saldo_finale DECIMAL(12,2) GENERATED ALWAYS AS (
        CASE 
            WHEN natura = 'DARE' THEN saldo_dare - saldo_avere
            ELSE saldo_avere - saldo_dare
        END
    ) STORED,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    created_by INT,
    updated_by INT,
    
    CONSTRAINT fk_piano_conti_condominio FOREIGN KEY (condominio_id) REFERENCES condomini(id) ON DELETE CASCADE,
    CONSTRAINT fk_piano_conti_created_by FOREIGN KEY (created_by) REFERENCES users(id),
    CONSTRAINT fk_piano_conti_updated_by FOREIGN KEY (updated_by) REFERENCES users(id),
    UNIQUE KEY unique_conto_condominio (condominio_id, codice),
    INDEX idx_tipo_natura (tipo_conto, natura),
    INDEX idx_gestione (gestione),
    INDEX idx_saldi (saldo_finale, attivo)
) COMMENT = 'Piano dei conti a 3 livelli con saldi automatici';

-- 2. GESTIONI CONTABILI (MULTI-ESERCIZIO)
CREATE TABLE gestioni_contabili (
    id INT PRIMARY KEY AUTO_INCREMENT,
    condominio_id INT NOT NULL,
    anno_riferimento YEAR NOT NULL,
    tipo_gestione ENUM('ORDINARIA','RISCALDAMENTO','STRAORDINARIA') NOT NULL,
    denominazione VARCHAR(255) NOT NULL,
    descrizione TEXT,
    data_inizio DATE NOT NULL,
    data_fine DATE NOT NULL,
    data_chiusura DATE NULL COMMENT 'Data effettiva chiusura contabile',
    stato ENUM('APERTA','PROVVISORIA','CHIUSA','APPROVATA') DEFAULT 'APERTA',
    protocollo_prefix VARCHAR(10) COMMENT 'Prefisso protocollo: ORD2025, RISC2025, STR2025',
    ultimo_protocollo INT DEFAULT 0,
    saldo_iniziale DECIMAL(12,2) DEFAULT 0.00,
    saldo_finale DECIMAL(12,2) DEFAULT 0.00,
    totale_costi DECIMAL(12,2) DEFAULT 0.00,
    totale_ricavi DECIMAL(12,2) DEFAULT 0.00,
    conguaglio DECIMAL(12,2) DEFAULT 0.00,
    approvata_assemblea DATE NULL,
    verbale_approvazione VARCHAR(255) NULL,
    budget_preventivo DECIMAL(12,2) DEFAULT 0.00,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    created_by INT,
    updated_by INT,
    
    CONSTRAINT fk_gestioni_condominio FOREIGN KEY (condominio_id) REFERENCES condomini(id) ON DELETE CASCADE,
    CONSTRAINT fk_gestioni_created_by FOREIGN KEY (created_by) REFERENCES users(id),
    CONSTRAINT fk_gestioni_updated_by FOREIGN KEY (updated_by) REFERENCES users(id),
    UNIQUE KEY unique_gestione_anno (condominio_id, anno_riferimento, tipo_gestione),
    INDEX idx_stato_gestione (stato, tipo_gestione),
    INDEX idx_date_gestione (data_inizio, data_fine)
) COMMENT = 'Gestioni contabili multiple per condominio con protocolli separati';

-- 3. CONTI BANCARI E CASSE
CREATE TABLE conti_bancari (
    id INT PRIMARY KEY AUTO_INCREMENT,
    condominio_id INT NOT NULL,
    tipo_conto ENUM('BANCARIO','POSTALE','PAYPAL','STRIPE','CASSA','SATISPAY','ALTRO') NOT NULL,
    denominazione VARCHAR(255) NOT NULL,
    descrizione TEXT,
    banca VARCHAR(255) NULL,
    filiale VARCHAR(255) NULL,
    iban VARCHAR(34) NULL,
    swift VARCHAR(11) NULL,
    abi VARCHAR(5) NULL,
    cab VARCHAR(5) NULL,
    numero_conto VARCHAR(50) NULL,
    conto_piano_conti_id INT NOT NULL COMMENT 'Collegamento al piano dei conti',
    saldo_iniziale DECIMAL(12,2) DEFAULT 0.00,
    saldo_attuale DECIMAL(12,2) DEFAULT 0.00,
    data_ultimo_movimento DATE NULL,
    attivo BOOLEAN DEFAULT TRUE,
    api_enabled BOOLEAN DEFAULT FALSE COMMENT 'Abilitazione sync automatica',
    api_config JSON NULL COMMENT 'Configurazioni API banca',
    limite_scoperto DECIMAL(12,2) DEFAULT 0.00,
    commissioni_fisse DECIMAL(10,2) DEFAULT 0.00,
    note TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    created_by INT,
    updated_by INT,
    
    CONSTRAINT fk_conti_bancari_condominio FOREIGN KEY (condominio_id) REFERENCES condomini(id) ON DELETE CASCADE,
    CONSTRAINT fk_conti_bancari_piano_conti FOREIGN KEY (conto_piano_conti_id) REFERENCES piano_conti(id),
    CONSTRAINT fk_conti_bancari_created_by FOREIGN KEY (created_by) REFERENCES users(id),
    CONSTRAINT fk_conti_bancari_updated_by FOREIGN KEY (updated_by) REFERENCES users(id),
    UNIQUE KEY unique_iban_condominio (condominio_id, iban),
    INDEX idx_tipo_attivo (tipo_conto, attivo),
    INDEX idx_saldo_data (saldo_attuale, data_ultimo_movimento)
) COMMENT = 'Gestione conti bancari, casse e sistemi di pagamento';

-- 4. REGISTRO PRIMA NOTA (PRE-ELABORAZIONE)
CREATE TABLE registro_prima_nota (
    id INT PRIMARY KEY AUTO_INCREMENT,
    condominio_id INT NOT NULL,
    gestione_id INT NOT NULL,
    protocollo_gestione VARCHAR(20) COMMENT 'Protocollo specifico gestione: ORD2025/001',
    protocollo_generale VARCHAR(20) COMMENT 'Protocollo annuale master: 2025/1234',
    data_registrazione DATE NOT NULL,
    data_competenza DATE NOT NULL,
    data_scadenza DATE NULL,
    descrizione TEXT NOT NULL,
    documento_tipo ENUM('FATTURA_ATTIVA','FATTURA_PASSIVA','RICEVUTA','BONIFICO','VERSAMENTO','NOTA_CREDITO','NOTA_DEBITO','ALTRO') NOT NULL,
    documento_numero VARCHAR(100),
    documento_data DATE,
    documento_serie VARCHAR(20),
    fornitore_id INT NULL,
    condomino_id INT NULL,
    importo_imponibile DECIMAL(10,2) DEFAULT 0.00,
    importo_iva DECIMAL(10,2) DEFAULT 0.00,
    importo_totale DECIMAL(10,2) NOT NULL,
    ritenuta_acconto DECIMAL(10,2) DEFAULT 0.00,
    percentuale_ritenuta DECIMAL(5,2) DEFAULT 0.00,
    causale_ritenuta VARCHAR(100) NULL,
    split_payment BOOLEAN DEFAULT FALSE,
    reverse_charge BOOLEAN DEFAULT FALSE,
    codice_iva VARCHAR(20) NULL,
    stato ENUM('BOZZA','VALIDATO','CONTABILIZZATO','ANNULLATO','STORNATO') DEFAULT 'BOZZA',
    urgente BOOLEAN DEFAULT FALSE,
    note TEXT,
    validato_da INT NULL,
    validato_at TIMESTAMP NULL,
    contabilizzato_da INT NULL,
    contabilizzato_at TIMESTAMP NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    created_by INT NOT NULL,
    updated_by INT,
    
    CONSTRAINT fk_prima_nota_condominio FOREIGN KEY (condominio_id) REFERENCES condomini(id) ON DELETE CASCADE,
    CONSTRAINT fk_prima_nota_gestione FOREIGN KEY (gestione_id) REFERENCES gestioni_contabili(id),
    CONSTRAINT fk_prima_nota_fornitore FOREIGN KEY (fornitore_id) REFERENCES fornitori(id),
    CONSTRAINT fk_prima_nota_condomino FOREIGN KEY (condomino_id) REFERENCES condomini_proprietari(id),
    CONSTRAINT fk_prima_nota_validato_da FOREIGN KEY (validato_da) REFERENCES users(id),
    CONSTRAINT fk_prima_nota_contabilizzato_da FOREIGN KEY (contabilizzato_da) REFERENCES users(id),
    CONSTRAINT fk_prima_nota_created_by FOREIGN KEY (created_by) REFERENCES users(id),
    CONSTRAINT fk_prima_nota_updated_by FOREIGN KEY (updated_by) REFERENCES users(id),
    INDEX idx_protocolli (protocollo_gestione, protocollo_generale),
    INDEX idx_stato_competenza (stato, data_competenza),
    INDEX idx_scadenze_urgenti (data_scadenza, urgente, stato),
    INDEX idx_importi (importo_totale, ritenuta_acconto)
) COMMENT = 'Registro prima nota per pre-elaborazione documenti';

-- 5. TRANSAZIONI CONTABILI (LIBRO MASTRO)
CREATE TABLE transazioni_contabili (
    id INT PRIMARY KEY AUTO_INCREMENT,
    condominio_id INT NOT NULL,
    gestione_id INT NOT NULL,
    prima_nota_id INT NULL COMMENT 'Collegamento opzionale a prima nota',
    numero_transazione VARCHAR(20) NOT NULL COMMENT 'Numerazione progressiva: TC2025/001234',
    data_transazione DATE NOT NULL,
    data_competenza DATE NOT NULL,
    descrizione TEXT NOT NULL,
    importo_totale DECIMAL(12,2) NOT NULL,
    tipo_transazione ENUM('REGISTRAZIONE','PAGAMENTO','INCASSO','GIROCONTO','STORNO','CHIUSURA') NOT NULL,
    stato ENUM('APERTA','CHIUSA','ANNULLATA','STORNATA') DEFAULT 'APERTA',
    quadratura_ok BOOLEAN DEFAULT FALSE COMMENT 'Verifica dare=avere automatica',
    revisione_richiesta BOOLEAN DEFAULT FALSE,
    note TEXT,
    documento_collegato VARCHAR(500) NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    created_by INT NOT NULL,
    updated_by INT,
    
    CONSTRAINT fk_transazioni_condominio FOREIGN KEY (condominio_id) REFERENCES condomini(id) ON DELETE CASCADE,
    CONSTRAINT fk_transazioni_gestione FOREIGN KEY (gestione_id) REFERENCES gestioni_contabili(id),
    CONSTRAINT fk_transazioni_prima_nota FOREIGN KEY (prima_nota_id) REFERENCES registro_prima_nota(id),
    CONSTRAINT fk_transazioni_created_by FOREIGN KEY (created_by) REFERENCES users(id),
    CONSTRAINT fk_transazioni_updated_by FOREIGN KEY (updated_by) REFERENCES users(id),
    UNIQUE KEY unique_numero_transazione (condominio_id, numero_transazione),
    INDEX idx_data_gestione (data_transazione, gestione_id),
    INDEX idx_quadratura_stato (quadratura_ok, stato),
    INDEX idx_competenza_tipo (data_competenza, tipo_transazione)
) COMMENT = 'Transazioni contabili del libro mastro';

-- 6. RIGHE MOVIMENTI CONTABILI (DARE/AVERE)
CREATE TABLE righe_movimenti_contabili (
    id INT PRIMARY KEY AUTO_INCREMENT,
    transazione_id INT NOT NULL,
    conto_id INT NOT NULL,
    tipo_movimento ENUM('DARE','AVERE') NOT NULL,
    importo DECIMAL(10,2) NOT NULL,
    descrizione_riga VARCHAR(255),
    riferimento_documento VARCHAR(100) NULL,
    fornitore_id INT NULL,
    condomino_id INT NULL,
    unita_immobiliare_id INT NULL,
    conto_bancario_id INT NULL,
    data_scadenza DATE NULL COMMENT 'Per gestione crediti/debiti',
    liquidato BOOLEAN DEFAULT FALSE,
    data_liquidazione DATE NULL,
    note_riga TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_by INT,
    
    CONSTRAINT fk_righe_transazione FOREIGN KEY (transazione_id) REFERENCES transazioni_contabili(id) ON DELETE CASCADE,
    CONSTRAINT fk_righe_conto FOREIGN KEY (conto_id) REFERENCES piano_conti(id),
    CONSTRAINT fk_righe_fornitore FOREIGN KEY (fornitore_id) REFERENCES fornitori(id),
    CONSTRAINT fk_righe_condomino FOREIGN KEY (condomino_id) REFERENCES condomini_proprietari(id),
    CONSTRAINT fk_righe_unita FOREIGN KEY (unita_immobiliare_id) REFERENCES unita_immobiliari(id),
    CONSTRAINT fk_righe_conto_bancario FOREIGN KEY (conto_bancario_id) REFERENCES conti_bancari(id),
    CONSTRAINT fk_righe_created_by FOREIGN KEY (created_by) REFERENCES users(id),
    INDEX idx_conto_tipo (conto_id, tipo_movimento),
    INDEX idx_liquidazione (liquidato, data_scadenza),
    INDEX idx_importo_movimento (importo, tipo_movimento),
    INDEX idx_soggetti (fornitore_id, condomino_id, unita_immobiliare_id)
) COMMENT = 'Righe dettaglio movimenti in dare e avere';

-- 7. MOVIMENTI BANCARI
CREATE TABLE movimenti_bancari (
    id INT PRIMARY KEY AUTO_INCREMENT,
    conto_bancario_id INT NOT NULL,
    data_movimento DATE NOT NULL,
    data_valuta DATE NOT NULL,
    data_contabile DATE NOT NULL,
    descrizione TEXT NOT NULL,
    importo DECIMAL(10,2) NOT NULL,
    tipo_movimento ENUM('ENTRATA','USCITA') NOT NULL,
    causale VARCHAR(255),
    causale_abi VARCHAR(10) NULL COMMENT 'Codice ABI causale',
    riferimento_bancario VARCHAR(100),
    cro VARCHAR(30) NULL,
    trn VARCHAR(50) NULL,
    ordinante VARCHAR(255) NULL,
    beneficiario VARCHAR(255) NULL,
    iban_ordinante VARCHAR(34) NULL,
    iban_beneficiario VARCHAR(34) NULL,
    commissioni DECIMAL(8,2) DEFAULT 0.00,
    transazione_contabile_id INT NULL COMMENT 'Collegamento a contabilità',
    riconciliato BOOLEAN DEFAULT FALSE,
    riconciliato_at TIMESTAMP NULL,
    riconciliato_da INT NULL,
    automatico BOOLEAN DEFAULT FALSE COMMENT 'Importato automaticamente',
    note TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    CONSTRAINT fk_movimenti_conto_bancario FOREIGN KEY (conto_bancario_id) REFERENCES conti_bancari(id) ON DELETE CASCADE,
    CONSTRAINT fk_movimenti_transazione FOREIGN KEY (transazione_contabile_id) REFERENCES transazioni_contabili(id),
    CONSTRAINT fk_movimenti_riconciliato_da FOREIGN KEY (riconciliato_da) REFERENCES users(id),
    INDEX idx_riconciliazione (riconciliato, data_movimento),
    INDEX idx_importo_tipo (importo, tipo_movimento),
    INDEX idx_date_movimento (data_movimento, data_valuta),
    INDEX idx_causali (causale_abi, causale),
    INDEX idx_soggetti (ordinante, beneficiario)
) COMMENT = 'Movimenti estratto conto bancario con riconciliazione';

-- 8. SISTEMA RITENUTE FISCALI
CREATE TABLE ritenute_fiscali (
    id INT PRIMARY KEY AUTO_INCREMENT,
    condominio_id INT NOT NULL,
    fattura_prima_nota_id INT NOT NULL,
    fornitore_id INT NOT NULL,
    anno_riferimento YEAR NOT NULL,
    data_fattura DATE NOT NULL,
    numero_fattura VARCHAR(100) NOT NULL,
    importo_imponibile DECIMAL(10,2) NOT NULL,
    percentuale_ritenuta DECIMAL(5,2) NOT NULL,
    importo_ritenuta DECIMAL(10,2) NOT NULL,
    codice_tributo VARCHAR(10) NOT NULL COMMENT 'Codice tributo F24',
    mese_competenza VARCHAR(7) NOT NULL COMMENT 'Formato: 2025-03',
    data_scadenza_versamento DATE NOT NULL COMMENT 'Entro il 16 del mese successivo',
    versata BOOLEAN DEFAULT FALSE,
    data_versamento DATE NULL,
    importo_versato DECIMAL(10,2) NULL,
    f24_generato BOOLEAN DEFAULT FALSE,
    f24_path VARCHAR(500) NULL,
    f24_numero VARCHAR(50) NULL,
    transazione_versamento_id INT NULL,
    note TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    CONSTRAINT fk_ritenute_condominio FOREIGN KEY (condominio_id) REFERENCES condomini(id) ON DELETE CASCADE,
    CONSTRAINT fk_ritenute_prima_nota FOREIGN KEY (fattura_prima_nota_id) REFERENCES registro_prima_nota(id),
    CONSTRAINT fk_ritenute_fornitore FOREIGN KEY (fornitore_id) REFERENCES fornitori(id),
    CONSTRAINT fk_ritenute_transazione FOREIGN KEY (transazione_versamento_id) REFERENCES transazioni_contabili(id),
    INDEX idx_scadenze (data_scadenza_versamento, versata),
    INDEX idx_competenza (mese_competenza, condominio_id),
    INDEX idx_anno_fornitore (anno_riferimento, fornitore_id),
    INDEX idx_versamenti (versata, data_versamento)
) COMMENT = 'Gestione ritenute d acconto con F24 automatico';

-- 9. BILANCI DI CHIUSURA
CREATE TABLE bilanci_chiusura (
    id INT PRIMARY KEY AUTO_INCREMENT,
    condominio_id INT NOT NULL,
    gestione_id INT NOT NULL,
    tipo_bilancio ENUM('PREVENTIVO','CONSUNTIVO','STRAORDINARIO') NOT NULL,
    anno_riferimento YEAR NOT NULL,
    data_chiusura DATE NOT NULL,
    data_approvazione DATE NULL,
    totale_attivo DECIMAL(12,2) NOT NULL DEFAULT 0.00,
    totale_passivo DECIMAL(12,2) NOT NULL DEFAULT 0.00,
    totale_costi DECIMAL(12,2) NOT NULL DEFAULT 0.00,
    totale_ricavi DECIMAL(12,2) NOT NULL DEFAULT 0.00,
    conguaglio_gestione DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT 'Positivo=credito condominio, Negativo=debito',
    fondi_disponibili DECIMAL(12,2) NOT NULL DEFAULT 0.00,
    fondi_impegnati DECIMAL(12,2) NOT NULL DEFAULT 0.00,
    stato ENUM('BOZZA','PROVVISORIO','APPROVATO','ARCHIVIATO') DEFAULT 'BOZZA',
    verbale_assemblea VARCHAR(255) NULL,
    delibera_assemblea VARCHAR(255) NULL,
    note TEXT,
    pdf_path VARCHAR(500) NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    created_by INT,
    
    CONSTRAINT fk_bilanci_condominio FOREIGN KEY (condominio_id) REFERENCES condomini(id) ON DELETE CASCADE,
    CONSTRAINT fk_bilanci_gestione FOREIGN KEY (gestione_id) REFERENCES gestioni_contabili(id),
    CONSTRAINT fk_bilanci_created_by FOREIGN KEY (created_by) REFERENCES users(id),
    UNIQUE KEY unique_bilancio_gestione (gestione_id, tipo_bilancio),
    INDEX idx_data_stato (data_chiusura, stato),
    INDEX idx_anno_tipo (anno_riferimento, tipo_bilancio)
) COMMENT = 'Bilanci di chiusura per gestioni';

-- 10. AUDIT TRAIL COMPLETO
CREATE TABLE audit_contabile (
    id INT PRIMARY KEY AUTO_INCREMENT,
    condominio_id INT NOT NULL,
    tabella_riferimento VARCHAR(100) NOT NULL,
    record_id INT NOT NULL,
    operazione ENUM('INSERT','UPDATE','DELETE') NOT NULL,
    dati_precedenti JSON NULL,
    dati_nuovi JSON NULL,
    campo_modificato VARCHAR(100) NULL,
    valore_precedente TEXT NULL,
    valore_nuovo TEXT NULL,
    user_id INT NOT NULL,
    ip_address VARCHAR(45),
    user_agent TEXT,
    session_id VARCHAR(100),
    timestamp_operazione TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    CONSTRAINT fk_audit_condominio FOREIGN KEY (condominio_id) REFERENCES condomini(id) ON DELETE CASCADE,
    CONSTRAINT fk_audit_user FOREIGN KEY (user_id) REFERENCES users(id),
    INDEX idx_tabella_record (tabella_riferimento, record_id),
    INDEX idx_condominio_timestamp (condominio_id, timestamp_operazione),
    INDEX idx_user_operazione (user_id, operazione),
    INDEX idx_audit_sessione (session_id, timestamp_operazione)
) COMMENT = 'Audit completo di tutte le modifiche contabili';

-- 11. TABELLE MILLESIMALI STRUTTURATE
CREATE TABLE tipologie_tabelle_millesimali (
    id INT PRIMARY KEY AUTO_INCREMENT,
    condominio_id INT NOT NULL,
    codice VARCHAR(20) NOT NULL,
    denominazione VARCHAR(255) NOT NULL,
    descrizione TEXT,
    tipo_ripartizione ENUM('MILLESIMI','PERCENTUALE','IMPORTO_FISSO','UNITA_UTILIZZO') NOT NULL,
    attiva BOOLEAN DEFAULT TRUE,
    ordine_visualizzazione INT DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    CONSTRAINT fk_tipologie_tabelle_condominio FOREIGN KEY (condominio_id) REFERENCES condomini(id) ON DELETE CASCADE,
    UNIQUE KEY unique_codice_condominio (condominio_id, codice),
    INDEX idx_tipo_attiva (tipo_ripartizione, attiva)
) COMMENT = 'Tipologie tabelle millesimali per condominio';

CREATE TABLE tabelle_millesimali (
    id INT PRIMARY KEY AUTO_INCREMENT,
    tipologia_id INT NOT NULL,
    unita_immobiliare_id INT NOT NULL,
    condomino_id INT NOT NULL,
    valore_millesimi DECIMAL(8,5) NOT NULL DEFAULT 0.00000,
    percentuale DECIMAL(5,2) NULL,
    importo_fisso DECIMAL(10,2) NULL,
    unita_utilizzo INT NULL,
    data_validita_da DATE NOT NULL,
    data_validita_a DATE NULL,
    attiva BOOLEAN DEFAULT TRUE,
    note TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    CONSTRAINT fk_tabelle_tipologia FOREIGN KEY (tipologia_id) REFERENCES tipologie_tabelle_millesimali(id) ON DELETE CASCADE,
    CONSTRAINT fk_tabelle_unita FOREIGN KEY (unita_immobiliare_id) REFERENCES unita_immobiliari(id),
    CONSTRAINT fk_tabelle_condomino FOREIGN KEY (condomino_id) REFERENCES condomini_proprietari(id),
    UNIQUE KEY unique_tabella_unita_validita (tipologia_id, unita_immobiliare_id, data_validita_da),
    INDEX idx_validita (data_validita_da, data_validita_a, attiva),
    INDEX idx_millesimi (valore_millesimi)
) COMMENT = 'Tabelle millesimali con storico modifiche';

-- =============================================
-- TRIGGERS AUTOMATICI
-- =============================================

DELIMITER //

-- Trigger aggiornamento saldi piano conti
CREATE TRIGGER aggiorna_saldo_piano_conti_insert
AFTER INSERT ON righe_movimenti_contabili
FOR EACH ROW
BEGIN
    IF NEW.tipo_movimento = 'DARE' THEN
        UPDATE piano_conti 
        SET saldo_dare = saldo_dare + NEW.importo,
            updated_at = CURRENT_TIMESTAMP
        WHERE id = NEW.conto_id;
    ELSE
        UPDATE piano_conti 
        SET saldo_avere = saldo_avere + NEW.importo,
            updated_at = CURRENT_TIMESTAMP
        WHERE id = NEW.conto_id;
    END IF;
END//

CREATE TRIGGER aggiorna_saldo_piano_conti_update
AFTER UPDATE ON righe_movimenti_contabili
FOR EACH ROW
BEGIN
    -- Reversa vecchi valori
    IF OLD.tipo_movimento = 'DARE' THEN
        UPDATE piano_conti 
        SET saldo_dare = saldo_dare - OLD.importo
        WHERE id = OLD.conto_id;
    ELSE
        UPDATE piano_conti 
        SET saldo_avere = saldo_avere - OLD.importo
        WHERE id = OLD.conto_id;
    END IF;
    
    -- Applica nuovi valori
    IF NEW.tipo_movimento = 'DARE' THEN
        UPDATE piano_conti 
        SET saldo_dare = saldo_dare + NEW.importo,
            updated_at = CURRENT_TIMESTAMP
        WHERE id = NEW.conto_id;
    ELSE
        UPDATE piano_conti 
        SET saldo_avere = saldo_avere + NEW.importo,
            updated_at = CURRENT_TIMESTAMP
        WHERE id = NEW.conto_id;
    END IF;
END//

CREATE TRIGGER aggiorna_saldo_piano_conti_delete
AFTER DELETE ON righe_movimenti_contabili
FOR EACH ROW
BEGIN
    IF OLD.tipo_movimento = 'DARE' THEN
        UPDATE piano_conti 
        SET saldo_dare = saldo_dare - OLD.importo,
            updated_at = CURRENT_TIMESTAMP
        WHERE id = OLD.conto_id;
    ELSE
        UPDATE piano_conti 
        SET saldo_avere = saldo_avere - OLD.importo,
            updated_at = CURRENT_TIMESTAMP
        WHERE id = OLD.conto_id;
    END IF;
END//

-- Trigger aggiornamento saldi bancari
CREATE TRIGGER aggiorna_saldo_bancario_insert
AFTER INSERT ON movimenti_bancari
FOR EACH ROW
BEGIN
    IF NEW.tipo_movimento = 'ENTRATA' THEN
        UPDATE conti_bancari 
        SET saldo_attuale = saldo_attuale + NEW.importo,
            data_ultimo_movimento = NEW.data_movimento,
            updated_at = CURRENT_TIMESTAMP
        WHERE id = NEW.conto_bancario_id;
    ELSE
        UPDATE conti_bancari 
        SET saldo_attuale = saldo_attuale - NEW.importo,
            data_ultimo_movimento = NEW.data_movimento,
            updated_at = CURRENT_TIMESTAMP
        WHERE id = NEW.conto_bancario_id;
    END IF;
END//

-- Trigger controllo quadratura transazioni
CREATE TRIGGER verifica_quadratura_transazione
AFTER INSERT ON righe_movimenti_contabili
FOR EACH ROW
BEGIN
    DECLARE totale_dare DECIMAL(12,2);
    DECLARE totale_avere DECIMAL(12,2);
    
    SELECT 
        COALESCE(SUM(CASE WHEN tipo_movimento = 'DARE' THEN importo ELSE 0 END), 0),
        COALESCE(SUM(CASE WHEN tipo_movimento = 'AVERE' THEN importo ELSE 0 END), 0)
    INTO totale_dare, totale_avere
    FROM righe_movimenti_contabili 
    WHERE transazione_id = NEW.transazione_id;
    
    UPDATE transazioni_contabili 
    SET quadratura_ok = (totale_dare = totale_avere),
        importo_totale = totale_dare,
        updated_at = CURRENT_TIMESTAMP
    WHERE id = NEW.transazione_id;
END//

-- Trigger auto-generazione protocolli
CREATE TRIGGER genera_protocollo_prima_nota
BEFORE INSERT ON registro_prima_nota
FOR EACH ROW
BEGIN
    DECLARE nuovo_protocollo INT;
    DECLARE prefix_gestione VARCHAR(10);
    
    -- Ottieni prefix gestione
    SELECT protocollo_prefix INTO prefix_gestione 
    FROM gestioni_contabili 
    WHERE id = NEW.gestione_id;
    
    -- Incrementa e ottieni nuovo numero protocollo
    UPDATE gestioni_contabili 
    SET ultimo_protocollo = ultimo_protocollo + 1 
    WHERE id = NEW.gestione_id;
    
    SELECT ultimo_protocollo INTO nuovo_protocollo
    FROM gestioni_contabili 
    WHERE id = NEW.gestione_id;
    
    -- Assegna protocolli
    SET NEW.protocollo_gestione = CONCAT(prefix_gestione, '/', LPAD(nuovo_protocollo, 3, '0'));
    
    -- Protocollo generale basato su anno
    IF NEW.protocollo_generale IS NULL THEN
        SET NEW.protocollo_generale = CONCAT(YEAR(NEW.data_registrazione), '/', LPAD(nuovo_protocollo, 4, '0'));
    END IF;
END//

-- Trigger audit automatico
CREATE TRIGGER audit_piano_conti_update
AFTER UPDATE ON piano_conti
FOR EACH ROW
BEGIN
    INSERT INTO audit_contabile (
        condominio_id, tabella_riferimento, record_id, operazione,
        dati_precedenti, dati_nuovi, user_id, ip_address
    ) VALUES (
        NEW.condominio_id, 'piano_conti', NEW.id, 'UPDATE',
        JSON_OBJECT('saldo_dare', OLD.saldo_dare, 'saldo_avere', OLD.saldo_avere),
        JSON_OBJECT('saldo_dare', NEW.saldo_dare, 'saldo_avere', NEW.saldo_avere),
        COALESCE(NEW.updated_by, NEW.created_by), 
        COALESCE(@user_ip, '0.0.0.0')
    );
END//

DELIMITER ;

-- =============================================
-- INDICI PER PERFORMANCE
-- =============================================

-- Indici compositi per query frequenti
CREATE INDEX idx_prima_nota_gestione_stato ON registro_prima_nota (gestione_id, stato, data_competenza);
CREATE INDEX idx_transazioni_gestione_data ON transazioni_contabili (gestione_id, data_transazione, stato);
CREATE INDEX idx_righe_conto_data ON righe_movimenti_contabili (conto_id, transazione_id);
CREATE INDEX idx_movimenti_bancari_riconciliazione ON movimenti_bancari (conto_bancario_id, riconciliato, data_movimento);
CREATE INDEX idx_ritenute_scadenze ON ritenute_fiscali (condominio_id, data_scadenza_versamento, versata);

-- =============================================
-- VISTE UTILI
-- =============================================

-- Vista bilancio di verifica
CREATE VIEW vista_bilancio_verifica AS
SELECT 
    pc.condominio_id,
    gc.tipo_gestione,
    gc.anno_riferimento,
    pc.codice,
    pc.denominazione,
    pc.tipo_conto,
    pc.natura,
    pc.saldo_dare,
    pc.saldo_avere,
    pc.saldo_finale
FROM piano_conti pc
JOIN gestioni_contabili gc ON pc.gestione IN ('TUTTE', gc.tipo_gestione)
WHERE pc.attivo = TRUE
ORDER BY pc.condominio_id, gc.tipo_gestione, pc.codice;

-- Vista scadenze ritenute
CREATE VIEW vista_scadenze_ritenute AS
SELECT 
    rf.condominio_id,
    f.ragione_sociale,
    rf.data_scadenza_versamento,
    rf.importo_ritenuta,
    rf.versata,
    DATEDIFF(rf.data_scadenza_versamento, CURDATE()) AS giorni_scadenza
FROM ritenute_fiscali rf
JOIN fornitori f ON rf.fornitore_id = f.id
WHERE rf.versata = FALSE
ORDER BY rf.data_scadenza_versamento;

-- Vista movimenti non riconciliati
CREATE VIEW vista_movimenti_non_riconciliati AS
SELECT 
    cb.condominio_id,
    cb.denominazione AS conto,
    mb.data_movimento,
    mb.descrizione,
    mb.importo,
    mb.tipo_movimento,
    DATEDIFF(CURDATE(), mb.data_movimento) AS giorni_pendente
FROM movimenti_bancari mb
JOIN conti_bancari cb ON mb.conto_bancario_id = cb.id
WHERE mb.riconciliato = FALSE
ORDER BY mb.data_movimento DESC;

-- =============================================
-- STORED PROCEDURES UTILI
-- =============================================

DELIMITER //

-- Procedura chiusura gestione
CREATE PROCEDURE chiudi_gestione_contabile(
    IN p_gestione_id INT,
    IN p_data_chiusura DATE,
    IN p_user_id INT
)
BEGIN
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
        ROLLBACK;
        RESIGNAL;
    END;
    
    START TRANSACTION;
    
    -- Aggiorna stato gestione
    UPDATE gestioni_contabili 
    SET stato = 'CHIUSA',
        data_chiusura = p_data_chiusura,
        updated_by = p_user_id,
        updated_at = CURRENT_TIMESTAMP
    WHERE id = p_gestione_id;
    
    -- Calcola totali
    UPDATE gestioni_contabili gc
    SET totale_costi = (
        SELECT COALESCE(SUM(rmc.importo), 0)
        FROM righe_movimenti_contabili rmc
        JOIN transazioni_contabili tc ON rmc.transazione_id = tc.id
        JOIN piano_conti pc ON rmc.conto_id = pc.id
        WHERE tc.gestione_id = gc.id 
        AND pc.tipo_conto = 'COSTO'
        AND rmc.tipo_movimento = 'DARE'
    ),
    totale_ricavi = (
        SELECT COALESCE(SUM(rmc.importo), 0)
        FROM righe_movimenti_contabili rmc
        JOIN transazioni_contabili tc ON rmc.transazione_id = tc.id
        JOIN piano_conti pc ON rmc.conto_id = pc.id
        WHERE tc.gestione_id = gc.id 
        AND pc.tipo_conto = 'RICAVO'
        AND rmc.tipo_movimento = 'AVERE'
    )
    WHERE gc.id = p_gestione_id;
    
    -- Calcola conguaglio
    UPDATE gestioni_contabili 
    SET conguaglio = totale_ricavi - totale_costi
    WHERE id = p_gestione_id;
    
    COMMIT;
END//

DELIMITER ;

-- =============================================
-- COMMENTI FINALI
-- =============================================

/*
SISTEMA CONTABILE NETGESCON - CARATTERISTICHE PRINCIPALI:

1. PARTITA DOPPIA COMPLETA
   - Ogni movimento ha sempre dare = avere
   - Controlli automatici di quadratura
   - Saldi calcolati automaticamente via trigger

2. MULTI-GESTIONE
   - Ordinaria, Riscaldamento, Straordinarie separate
   - Protocolli indipendenti per gestione
   - Possibilità di spostare spese tra gestioni

3. SISTEMA PROTOCOLLI MULTIPLI
   - Protocollo generale annuale
   - Protocolli specifici per gestione
   - Numerazione automatica

4. RICONCILIAZIONE BANCARIA
   - Import automatico movimenti
   - Collegamento a transazioni contabili
   - Vista movimenti non riconciliati

5. GESTIONE RITENUTE AUTOMATICA
   - Calcolo automatico ritenute
   - Scadenzario F24
   - Generazione modelli

6. AUDIT COMPLETO
   - Tracking di ogni modifica
   - Storico modifiche dettagliato
   - Tracciabilità utenti

7. PERFORMANCE OTTIMIZZATE
   - Saldi pre-calcolati via trigger
   - Indici per query frequenti
   - Viste per report standard

PROSSIMI PASSI:
- Implementazione interfacce Laravel
- API per import dati automatici
- Report e stampe bilanci
- Dashboard contabile avanzata
*/
