using Microsoft.ML;
using Microsoft.ML.Data;
using SentimentAnalysis.DataStructures;

internal static class Program
{
    static void Main(string[] args)
    {
        var mlContext = new MLContext(seed: 1);
        var dataPath = Path.Combine(AppContext.BaseDirectory, "Data", "wikiDetoxAnnotated40kRows.tsv");
        Directory.CreateDirectory(Path.Combine(AppContext.BaseDirectory, "Models"));
        var modelPath = Path.Combine(AppContext.BaseDirectory, "Models", "SentimentModel.zip");

        IDataView dataView = mlContext.Data.LoadFromTextFile<SentimentIssue>(
            path: dataPath,
            hasHeader: true,
            separatorChar: '\t'
            );

        var dataProcessPipeline = mlContext.Transforms.Text.FeaturizeText(
            outputColumnName: "Features",
            inputColumnName: nameof(SentimentIssue.Text)
            );

        var trainer = mlContext.BinaryClassification.Trainers.SdcaLogisticRegression(
            labelColumnName: nameof(SentimentIssue.Label),
            featureColumnName: "Features"
            );

        var split = mlContext.Data.TrainTestSplit(dataView, testFraction: 0.2);
        var trainingData = split.TrainSet;
        var testData = split.TestSet;

        //trening
        var trainingPipeline = dataProcessPipeline.Append(trainer);
        var model = trainingPipeline.Fit(trainingData);

        //test
        var predictions = model.Transform(testData);
        var metrics = mlContext.BinaryClassification.Evaluate(
            data: predictions,
            labelColumnName: nameof(SentimentIssue.Label),
            scoreColumnName: "Score"
            );

        mlContext.Model.Save(model, trainingData.Schema, modelPath);
        Console.WriteLine($"Model zapisany do: {modelPath}");

        PrintMetrics(metrics);
    }

        private static void PrintMetrics(BinaryClassificationMetrics m)
    {
        Console.WriteLine("=============== Evaluation Metrics ===============");
        Console.WriteLine($"Accuracy:  {m.Accuracy:P2}");
        Console.WriteLine($"F1Score:   {m.F1Score:P2}");
        Console.WriteLine($"Positive Precision: {m.PositivePrecision:P2}");
        Console.WriteLine($"Positive Recall:    {m.PositiveRecall:P2}");
        Console.WriteLine($"Negative Precision: {m.NegativePrecision:P2}");
        Console.WriteLine($"Negative Recall:    {m.NegativeRecall:P2}");
        Console.WriteLine("==================================================");
    }
}
