//
//  lkf2026Tests.swift
//  LKF
//
//  Created by Alexander Holzer on 04.06.25.
//  Copyright © 2025 Alexander Holzer. All rights reserved.
//

import XCTest
@testable import lkfc

final class lkf2026Tests: XCTestCase {
    
    func createContextWith (model: UInt32, year: Int32? = nil, flags: Int32 = 0, lines : [String]) throws -> LKFContext {
        let c = try lkfcTests.createContextWith(model:model, flags: flags, lines:lines)
        if let year {
            c.setContextParameters(year: year)
        }
        return c
    }
    
    func createContextWith (metaDataContext: LKFMetaDataFilesContext, year: Int32? = nil, lines : [String]) throws -> LKFContext {
        
        let context = try LKFContext (metaDataContext: metaDataContext)
        do {
            for s in lines {
                try context.addLine(line: s)
            }
        }
        catch {
            print (error.localizedDescription)
        }
        
        return context
    }
    
    func combine (_ first:[String], _ second:[String]) -> [String] {
        return lkfcTests.combine(first, second)
    }
    
    static var fall_testWX5C = [
        "X01|K638|123||20250421|0725|I|19530403|65|M|AT|AT|8720|62041|||||||||15|J|2",
        "X02|K638|123||20250421|001|16211100|20250421|0725|J||||||N|65|",
        "X03|K638|123||20250421|C50.9|H|||2025049410",
        "X04|K638|123||20250421|ZN173||J|1|20250421|0741|18219500||",
        "X04|K638|123||20250421|ZN174||J|1|20250421|0725|16211100||"
    ]
    
    static var fall_testWX5C_combined = [
        "X04|K638|123||20250421|ZN180||J|1|20250421|0725|16211100||"
    ]
    
    func testWX5C () throws {
        var context = try createContextWith(model: 2025, lines: lkf2026Tests.fall_testWX5C)
        try context.execute()
        
        var resultLine = context.getResultLine(forIndex: 0)
        XCTAssert(resultLine == "X05|K638|123||20250421|MEL25.10|B|||130||||44||174", "result for 2025 differs")
        
        var errors = context.errorsWith (code:"WX5C")
        XCTAssert(errors == nil, "WX5C not expected in model 2025")
        
        context = try createContextWith(model: 2026, lines: lkf2026Tests.fall_testWX5C)
        try context.execute()
        
        errors = context.errorsWith (code:"WX5C")
        XCTAssert(errors != nil, "WX5C expected in model 2026")
        
        resultLine = context.getResultLine(forIndex: 0)
        XCTAssert(resultLine == "X05|K638|123||20250421|MEL25.10|B|||130||||44||174", "result for 2026 differs")
        
        let combined = combine(lkf2026Tests.fall_testWX5C, lkf2026Tests.fall_testWX5C_combined)
        
        context = try createContextWith(model: 2026, lines: combined)
        try context.execute()
        
        errors = context.errorsWith (code:"WX5C")
        XCTAssert(errors == nil, "WX5C not expected in model 2026 with ZN170")
        
        resultLine = context.getResultLine(forIndex: 0)
        XCTAssert(resultLine == "X05|K638|123||20250421|MEL25.09|C|||621||||||621", "result for 2026 differs")
    }
    
    static var fall_testWX5D = [
        "X01|K638|123||20250421|0725|I|19530403|65|M|AT|AT|8720|62041|||||||||15|J|2",
        "X02|K638|123||20250421|001|16211100|20250421|0725|J||||||N|65|",
        "X03|K638|123||20250421|C50.9|H|||2025049410",
        "X04|K638|123||20250421|DD040||J|1|20250421|0741|18219500||"
    ]
    
    static var fall_testWX5D_combined = [
        "X04|K638|123||20250421|DD010||J|1|20250421|0725|16211100||"
    ]
    
    func testWX5D () throws {
        var context = try createContextWith(model: 2025, lines: lkf2026Tests.fall_testWX5D)
        try context.execute()
        
        var resultLine = context.getResultLine(forIndex: 0)
        XCTAssert(resultLine == "X05|K638|123||20250421|MEL21.11|C|||653|475|||||1128", "result for 2025 differs")
        
        var errors = context.errorsWith (code:"WX5D")
        XCTAssert(errors == nil, "WX5D not expected in model 2025")
        
        context = try createContextWith(model: 2026, lines: lkf2026Tests.fall_testWX5D)
        try context.execute()
        
        errors = context.errorsWith (code:"WX5D")
        XCTAssert(errors != nil, "WX5D expected in model 2026")
        
        resultLine = context.getResultLine(forIndex: 0)
        XCTAssert(resultLine == "X05|K638|123||20250421|MEL21.11|C|||653|475|||||1128", "result for 2026 differs")
        
        let combined = combine(lkf2026Tests.fall_testWX5D, lkf2026Tests.fall_testWX5D_combined)
        
        context = try createContextWith(model: 2026, lines: combined)
        try context.execute()
        
        errors = context.errorsWith (code:"WX5D")
        XCTAssert(errors == nil, "WX5D not expected in model 2026 with DD010")
        
        resultLine = context.getResultLine(forIndex: 0)
        XCTAssert(resultLine == "X05|K638|123||20250421|MEL21.01|D|||694|462|||449||1605", "result for 2026 differs")
    }

    
    static var fall_testWX5E = [
        "X01|K638|123||20250421|0725|I|19530403|65|M|AT|AT|8720|62041|||||||||15|J|2",
        "X02|K638|123||20250421|001|16211100|20250421|0725|J||||||N|65|",
        "X03|K638|123||20250421|C50.9|H|||2025049410",
        "X04|K638|123||20250421|HM080||J|1|20250421|0741|18219500||"
    ]
    
    static var fall_testWX5E_combined = [
        "X04|K638|123||20250421|HM060||J|1|20250421|0725|16211100||"
    ]
    
    func testWX5E () throws {
        var context = try createContextWith(model: 2025, lines: lkf2026Tests.fall_testWX5E)
        try context.execute()
        
        var resultLine = context.getResultLine(forIndex: 0)
        XCTAssert(resultLine == "X05|K638|123||20250421|MEL29.02|D|||2103|50|||||2153", "result for 2025 differs")
        
        var errors = context.errorsWith (code:"WX5E")
        XCTAssert(errors == nil, "WX5E not expected in model 2025")
        
        context = try createContextWith(model: 2026, lines: lkf2026Tests.fall_testWX5E)
        try context.execute()
        
        errors = context.errorsWith (code:"WX5E")
        XCTAssert(errors != nil, "WX5E expected in model 2026")
        
        resultLine = context.getResultLine(forIndex: 0)
        XCTAssert(resultLine == "X05|K638|123||20250421|MEL29.02|D|||2103|50|||||2153", "result for 2026 differs")
        
        let combined = combine(lkf2026Tests.fall_testWX5E, lkf2026Tests.fall_testWX5E_combined)
        
        context = try createContextWith(model: 2026, lines: combined)
        try context.execute()
        
        errors = context.errorsWith (code:"WX5E")
        XCTAssert(errors == nil, "WX5E not expected in model 2026 with DD010")
        
        resultLine = context.getResultLine(forIndex: 0)
        XCTAssert(resultLine == "X05|K638|123||20250421|MEL29.02|D|||2103|50|||||2153", "result for 2026 differs")
    }

    
    static var fall_ambNoHD = [
        "X01|K706|345||20200121|0800|I|19710101|45|W|AT|AT|6410|70357|||||||||18|J|2",
        "X02|K706|345||20200121|001|16111300|20200121|0800|J||||||N|55|3009334550",
        "X04|K706|345||20200121|AP541||J|1|20200121|0800|16111300||3009334550",
        "X04|K706|345||20200121|ZN595||J|1|20200121|0800|16111300||3009334550"
    ]
    
    static var fall_ambNoHDZD = ["X03|K706|345||20200121|C50.9|Z|||2025049410"]
    
    func testAmbNoHD () throws {
        var context = try createContextWith(model: 2025, lines: lkf2026Tests.fall_ambNoHD)
        try context.execute()
        var errors = context.errorsWith (code:"WX56")
        XCTAssert(errors != nil, "WX56 expected in model 2025")
        
        let combines = combine(lkf2026Tests.fall_ambNoHD, lkf2026Tests.fall_ambNoHDZD)
        context = try createContextWith(model: 2025, lines: combines)
        try context.execute()
        errors = context.errorsWith (code:"WX56")
        XCTAssert(errors != nil, "WX56 expected in model 2025")
        
        context = try createContextWith(model: 2026, year: 2025, lines: lkf2026Tests.fall_ambNoHD)
        try context.execute()
        errors = context.errorsWith (code:"WX56")
        XCTAssert(errors != nil, "WX56 expected in model 2026")
        
        context = try createContextWith(model: 2026, year: 2025, lines: combines)
        try context.execute()
        errors = context.errorsWith (code:"WX56")
        XCTAssert(errors == nil, "WX56 not expected in model 2026")
        errors = context.errorsWith (code:"WX5F")
        XCTAssert(errors != nil, "WX5F expected in model 2026")
    }
    
    static var ambTod = [
        "X01|K638|20260101||20260101|0700|S|19510101|65|M|AT|AT|8720|62041|A|S||||S|20260101|1522|15|J|2",
        "X02|K638|20260101||20260101|001|16211100|20260101|0700|J||||||N|65|2022049410",
        "X02|K638|20260101||20260101|002|18219500|20260101|0740|J||||||N|65|2022049410",
        "X03|K638|20260101||20260101|C43.5|H|||2022049410",
        "X04|K638|20260101||20260101|QZ090||J|1|20260101|0741|18219500||",
        "X04|K638|20260101||20260101|QZ109||J|1|20260101|0725|16211100||",
        "X04|K638|20260101||20260101|QZ989||J|1|20260101|0725|16211100||"
    ]

    func testAmbTod () throws {
        var context = try createContextWith(model: 2025, year: 2026, lines: lkf2026Tests.ambTod)
        try context.execute()
        var errors = context.errorsWith (code:"EX0V")
        XCTAssert(errors != nil, "EX0V expected in model 2025")
        
        context = try createContextWith(model: 2026, lines: lkf2026Tests.ambTod)
        try context.execute()
        errors = context.errorsWith (code:"EX0V")
        XCTAssert(errors != nil, "EX0V expected in model 2026")
    }
    
    static var fall_ambUngHD = [
        "X01|K706|345||20260121|0800|I|19710101|45|W|AT|AT|6410|70357|||||||||18|J|2",
        "X02|K706|345||20260121|001|16111300|20260121|0800|J||||||N|55|3009334550",
        "X03|K706|345||20260121|911.9|H|||2025049410",
        "X04|K706|345||20260121|AP541||J|1|20260121|0800|16111300||3009334550",
        "X04|K706|345||20260121|ZN595||J|1|20260121|0800|16111300||3009334550"
    ]

    
    func testAmbUngHD () throws {
        var context = try createContextWith(model: 2025, year: 2026, lines: lkf2026Tests.fall_ambUngHD)
        try context.execute()
        var errors = context.errorsWith (code:"EX1M")
        XCTAssert(errors == nil, "EX1M not expected in model 2025")
        
        context = try createContextWith(model: 2026, lines: lkf2026Tests.fall_ambUngHD)
        try context.execute()
        errors = context.errorsWith (code:"EX1M")
        XCTAssert(errors != nil, "EX1M expected in model 2026")
      }

    static var fall_onko2026 = [
        "X01|K910|123||20250901|0751|S|19570101|55|W|AT|AT|1100|91001|W|P||||E|20250905|1727|07|J|4",
        "X02|K910|123||20250901|001|11115800|20250901|0751||||||11115800|N|55|",
        "X03|K910|123||20250901|A84.8|H|||",
        "X04|K910|123||20250901|XA250||J|1|20250901|1248|16912600||"
    ]
    
    func createContextWith (provider: LKFContextStammProvider, model: UInt32, year: Int32, lines: [String]) throws -> LKFContext {
        return try lkfcTests.createContextWith (provider:provider, model:model, year:year, lines:lines)
    }
    
    static var fall_onko2026diag = [
        "X01|K910|123||20250901|0751|S|19570101|55|W|AT|AT|1100|91001|W|P||||E|20250905|1727|07|J|4",
        "X02|K910|123||20250901|001|11115800|20250901|0751||||||11115800|N|55|",
        "X03|K910|123||20250901|B21.1|H|||",
        "X04|K910|123||20250901|XA250||J|1|20250901|1248|16912600||"
    ]
    
    func testOnkoB21 () throws {
        
        LKFContext.unloadStamm()
        let stammProvider = LKFContextStammProvider()
        stammProvider.add (file:"diaglist.dat", line:"B21.1    HDG08.03                             Gutartige Neubildung: Pankreas")

        var context = try createContextWith(model: 2025, lines: lkf2026Tests.fall_onko2026)
        try context.execute()
        var errors = context.errorsWith (code:"HX05")
        XCTAssert(errors != nil, "HX05 expected in model 2025")
        
        context = try createContextWith(model: 2026, year: 2025, lines: lkf2026Tests.fall_onko2026)
        try context.execute()
        errors = context.errorsWith (code:"HX05")
        XCTAssert(errors != nil, "HX05 expected in model 2025")
        
        context = try createContextWith(provider: stammProvider, model: 2025, year: 2025, lines: lkf2026Tests.fall_onko2026diag)
        try context.execute()
        errors = context.errorsWith (code:"HX05")
        XCTAssert(errors != nil, "HX05 expected in model 2025")
        
        context = try createContextWith(provider: stammProvider, model: 2026, year: 2025, lines: lkf2026Tests.fall_onko2026diag)
        try context.execute()
        errors = context.errorsWith (code:"HX05")
        XCTAssert(errors == nil, "HX05 not expected in model 2025")
    }
    
    override func setUpWithError() throws {
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }

    override func tearDownWithError() throws {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
    }

    func testExample() throws {
        // This is an example of a functional test case.
        // Use XCTAssert and related functions to verify your tests produce the correct results.
        // Any test you write for XCTest can be annotated as throws and async.
        // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
        // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
    }

    func testPerformanceExample() throws {
        // This is an example of a performance test case.
        self.measure {
            // Put the code you want to measure the time of here.
        }
    }

}
