module PSBoardDataBase

using CSV: nothingerror
using SQLite
using DBInterface
using Tables
using CSV
using DataFrames
using JLD2
using Dates

include("QaqcMasterLog.jl")
include("ClockParser.jl")
include("SlaveLogParser.jl")

include("create_table.jl")
include("DownloadCSVs.jl")
include("import_data.jl")

include("DispatchChecker.jl")
using .DispatchChecker

export create_database

@deprecate create_database_from_exported_csvs(dbpath::AbstractString; kw...) create_database(dbpath; kw...) false

"""
    create_database(
        dbpath::AbstractString;
        masterlog_dir::AbstractString,
        slavelog_dir::AbstractString,
        slavelog_result::AbstractString,
        single_run_csv::AbstractString = DownloadCSVs.download_single_run_csv(),
        runlist_csv::AbstractString = DownloadCSVs.download_runlist_csv(),
        dispatch_csv::AbstractString = DownloadCSVs.download_dispatch_csv(),
        hundred_csv::AbstractString = DownloadCSVs.download_hundred_run_csv(),
        jathubs_csv::AbstractString = DownloadCSVs.download_jathub_csv(),
    )

Create database at `dbpath` and import data from CSV and master log files.

Optionally, you can make a cache file to store parsed slave logs.

# Arguments

## Required
- `dbpath`: where the database will be created
- `masterlog_dir`: path to the directory (`log`) where all JATHub master logs are stored
- `slavelog_dir`: path to the directory where all JATHub slave logs are stored

## Optional
### Slave log cache
- `slavelog_result`: Filename of JLD2 where parsed slave logs are stored. If not specified, the data is not saved. See [JLD2 document](https://juliaio.github.io/JLD2.jl/stable/) for how to read/write JLD2 files.

### Source
By default, CSV files of Google Sheets are downloaded automatically.
If you want to use alternative CSV or are not online, you can specify the path of the CSVs manually.
- `single_run_csv`: CSV of single run results exported from the Google sheets database
- `runlist_csv`: CSV of run lists exported from the Google sheets database
- `dispatch_csv`: CSV of dispatch lists exported from the Google sheets database
- `hundred_csv`: CSV of 100 tests results exported from the Google sheets database
- `jathubs_csv`: CSV for jathub list used in QAQC. Used to add skew.
"""
function create_database(
    dbpath::AbstractString;
    masterlog_dir::AbstractString,
    slavelog_dir::AbstractString,
    kw...,
)
    db = create_empty_database(dbpath)

    single_result_df,
    runlist_table,
    dispatch_table,
    extra_100test_result_df,
    jathubs_table =
        map((
            (:single_run_csv, DownloadCSVs.download_single_run_csv),
            (:runlist_csv, DownloadCSVs.download_runlist_csv),
            (:dispatch_csv, DownloadCSVs.download_dispatch_csv),
            (:hundred_csv, DownloadCSVs.download_hundred_run_csv),
            (:jathubs_csv, DownloadCSVs.download_jathub_csv),
        )) do (key, dlfunc)
            if !haskey(kw, key)
                Channel{DataFrame}(1) do ch
                    csvfile = dlfunc()
                    df = CSV.read(csvfile, DataFrame)
                    put!(ch, df)
                end
            else
                Channel{DataFrame}(1) do ch
                    put!(ch, CSV.read(kw[key], DataFrame))
                end
            end
        end .|> first
    jld2_slavelog_path = if haskey(kw, :slavelog_result)
        kw[:slavelog_result]
    else
        nothing
    end
    jld2_slavelog = if isnothing(jld2_slavelog_path)
        nothing
    else
        jldopen(jld2_slavelog_path, "w")
    end

    insert_version_info(db)
    insert_qaqc_campaign_id(db)
    insert_qaqc_positions(db, jathubs_table)

    add_psboard_ids(db, single_result_df)
    add_qaqc_runlist_from_runlist(db, runlist_table)
    add_qaqc_single_result(db, single_result_df, runlist_table)
    add_qaqc_dispatch(db, dispatch_table)
    add_qaqc_runlist_from_masterlogs(db, masterlog_dir)
    add_qaqc_100test_result(db, extra_100test_result_df, slavelog_dir, jld2_slavelog)
    add_skew_from_slave_clk_logs(db, slavelog_dir)
    add_slavelog_result(db, slavelog_dir, jld2_slavelog)

    if !isnothing(jld2_slavelog)
        close(jld2_slavelog)
    end

    db
end

greet() = print("Hello World!")

end # module PSBoardDataBase
