using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using PolyTrader.Core.Configuration;
using PolyTrader.Modules.Accounting.Models;

namespace PolyTrader.Modules.Accounting.Persistence
{
    /// <summary>
    /// EF-Kontext des Accounting-Moduls (gleiche MySQL-DB, Tabellen mit Präfix acc_). Append-only
    /// Ledger mit Autoincrement-PKs und Unique-Index auf dem Idempotenz-Schlüssel (kein Doppel-Buchen).
    /// </summary>
    public class AccountingDbContext : DbContext
    {
        public AccountingDbContext(DbContextOptions<AccountingDbContext> options) : base(options) { }

        public DbSet<LedgerEntry> Ledger => Set<LedgerEntry>();
        public DbSet<IngestRun> IngestRuns => Set<IngestRun>();
        public DbSet<RawSnapshot> RawSnapshots => Set<RawSnapshot>();
        public DbSet<FxRate> FxRates => Set<FxRate>();

        protected override void OnModelCreating(ModelBuilder b)
        {
            b.Entity<LedgerEntry>(e =>
            {
                e.ToTable("acc_ledger");
                e.HasKey(x => x.Id);
                e.Property(x => x.Id).ValueGeneratedOnAdd();
                e.Property(x => x.EventType).HasConversion<string>().HasMaxLength(20);
                e.Property(x => x.TokenId).HasMaxLength(120);
                e.Property(x => x.MarketSlug).HasMaxLength(300);
                e.Property(x => x.Outcome).HasMaxLength(200);
                e.Property(x => x.Side).HasMaxLength(10);
                e.Property(x => x.Source).HasMaxLength(40);
                e.Property(x => x.TxHash).HasMaxLength(80);
                e.Property(x => x.IdempotencyKey).HasMaxLength(200);
                e.Property(x => x.Size).HasPrecision(28, 8);
                e.Property(x => x.PriceUsdc).HasPrecision(18, 6);
                e.Property(x => x.GrossUsdc).HasPrecision(28, 8);
                e.Property(x => x.FeeUsdc).HasPrecision(28, 8);
                e.Property(x => x.NetUsdc).HasPrecision(28, 8);
                e.HasIndex(x => x.IdempotencyKey).IsUnique();       // Idempotenz: kein Doppel-Buchen
                e.HasIndex(x => new { x.AccountId, x.Timestamp });
                e.HasIndex(x => x.EventType);
            });

            b.Entity<IngestRun>(e =>
            {
                e.ToTable("acc_ingest_runs");
                e.HasKey(x => x.Id);
                e.Property(x => x.Id).ValueGeneratedOnAdd();
                e.Property(x => x.Message).HasMaxLength(1000);
                e.Property(x => x.BalanceAnchorUsdc).HasPrecision(28, 8);
                e.Property(x => x.LedgerNetUsdc).HasPrecision(28, 8);
                e.Property(x => x.BalanceDeltaUsdc).HasPrecision(28, 8);
                e.HasIndex(x => new { x.AccountId, x.StartedAt });
            });

            b.Entity<RawSnapshot>(e =>
            {
                e.ToTable("acc_raw");
                e.HasKey(x => x.Id);
                e.Property(x => x.Id).ValueGeneratedOnAdd();
                e.Property(x => x.SourceKind).HasMaxLength(20);
                e.Property(x => x.Json).HasColumnType("longtext");
                e.HasIndex(x => x.IngestRunId);
            });

            b.Entity<FxRate>(e =>
            {
                e.ToTable("acc_fx_rates");
                e.HasKey(x => x.Date);
                e.Property(x => x.Date).HasColumnType("date");
                e.Property(x => x.UsdToEur).HasPrecision(18, 8);
                e.Property(x => x.Source).HasMaxLength(40);
            });
        }
    }

    /// <summary>Design-Time-Factory (fixe Server-Version → Migrations-Scaffolding OHNE DB-Verbindung).</summary>
    public class AccountingDbContextFactory : IDesignTimeDbContextFactory<AccountingDbContext>
    {
        public AccountingDbContext CreateDbContext(string[] args)
        {
            var conn = Environment.GetEnvironmentVariable("POLYTRADER_MYSQL")
                ?? "Server=localhost;Port=3306;Database=polytrader;User ID=root;Password=;";
            var options = new DbContextOptionsBuilder<AccountingDbContext>()
                .UseMySql(conn, DatabaseServerVersion.Value)
                .Options;
            return new AccountingDbContext(options);
        }
    }
}
