import pathlib
import sys
import shutil
import os
import argparse
import json

from create_md import create_md

# {scheme_name}
# 	├── {amplicon_size}
# 	│   └── {version}
# 	│       ├── primer.bed
# 	│       ├── amplicon.bed
# 	│       ├── reference_msa.fasta
# 	│       ├── README.md
# 	│       └── work
# 	│	        ├── config.json
# 	│	        ├── scheme.png
# 	│	        ├── scheme.html
# 	│	        └── output.log
# 	├── LICENSE
# 	└── README.md


LICENSE_TXT = """------------------------------------------------------------------------

This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/) 

![](https://i.creativecommons.org/l/by-sa/4.0/88x31.png)"""


def cli():
    description = "Generates a github repo for a primerscheme"
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument(
        "--schemedir",
        help="The top level of the scheme",
        type=pathlib.Path,
        required=True,
        nargs="+",
    )
    parser.add_argument(
        "--schemeoutdir",
        help="Where to save and init the scheme repo",
        type=pathlib.Path,
        # required=True,
        default=pathlib.Path("/Users/kentcg/primerschemes"),
    )
    parser.add_argument(
        "--mdoutdir",
        help="The _pages dir of the github pages repo",
        type=pathlib.Path,
        default=pathlib.Path("/Users/kentcg/ChrisgKent.github.io/docs/_posts"),
    )
    parser.add_argument(
        "--dryrun",
        help="The _pages dir of the github pages repo",
        type=bool,
        default=True,
    )
    parser.add_argument(
        "--version",
        help="The Scheme version",
        type=str,
        default="v0.1.0",
    )
    parser.add_argument(
        "--size",
        help="The Scheme version",
        type=int,
        default=1000,
    )
    parser.add_argument(
        "--pclass",
        help="The Scheme version",
        choices=["primerschemes", "primerpanels"],
        required=True,
    )

    args = parser.parse_args()
    return args


def create(
    scheme_outdir: pathlib.Path,
    md_outdir,
    primal_nf_dir,
    size,
    version,
    scheme_name,
    pclass,
):
    # Check if already exists in outdir/index.json
    with open(scheme_outdir / "index.json", "r") as index:
        index_json = json.load(index)

        pclass_json = index_json[pclass]

        if scheme_name in pclass_json:
            if size in pclass_json[scheme_name]:
                if version in pclass_json[scheme_name][size]:
                    raise sys.exit(
                        f"{scheme_name} {size} {version} already exists in index.json"
                    )  # type: ignore

    primal_nf_scheme_dir = primal_nf_dir / primal_nf_dir.name
    common_name, taxid = primal_nf_dir.name.split("--")

    # Get paths
    primer_bed = primal_nf_scheme_dir / "output.primer.bed"
    conf = primal_nf_scheme_dir / "config.json"
    amplicon_bed = primal_nf_scheme_dir / "output.amplicon.bed"
    logfile = primal_nf_scheme_dir / "work/file.log"

    pngs: list[pathlib.Path] = [x for x in primal_nf_scheme_dir.glob("*.png")]
    htmls: list[pathlib.Path] = [x for x in primal_nf_scheme_dir.glob("*.html")]

    msa = primal_nf_dir / f"{taxid}_final.fasta"

    ## Create output dirs
    output_dir: pathlib.Path = scheme_outdir / f"{pclass}/{scheme_name}"
    size_dir: pathlib.Path = pathlib.Path(output_dir / size)
    version_dir: pathlib.Path = pathlib.Path(size_dir / version)

    # Check all the files exist
    if not primer_bed.exists():
        return None
    if not conf.exists():
        return None
    if not amplicon_bed.exists():
        return None
    if not logfile.exists():
        return None
    if not msa.exists():
        return None
    if len(pngs) == 0:
        return None
    if len(htmls) == 0:
        return None
    if not primal_nf_scheme_dir.exists():
        return None

    # If the output dir doesn't exist
    if not output_dir.exists():
        output_dir.mkdir()

        # Create the main readme
        with open(output_dir / "README.md", "w") as mainreadme:
            mainreadme.write(f"# PrimerSchemes for {common_name}\n\n")
            mainreadme.write(
                f"These are autogenerated schemes for TAXID: [{taxid}](https://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?mode=Info&id={taxid}&lvl=3&lin=f&keep=1&srchmode=1&unlock)\n\nGenomes are scraped from the EBI API, and then filtered, phylogenetically downsampled and aligned, to produce the input for a new PrimalScheme algorithm\n\nFor details please see preprint: TBD\n\n"
            )
            mainreadme.write(LICENSE_TXT)

        # Copy the licenseassets/LICENSE
        shutil.copyfile(pathlib.Path("assets/LICENSE"), output_dir / "LICENSE")

    # Create the size dir if doesn't exist
    if not size_dir.exists():
        size_dir.mkdir()

    # Create the version dir if doesn't exist
    if not version_dir.exists():
        version_dir.mkdir()
    else:
        return None

    ## Copy top level files
    # Copy the primer.bed file
    shutil.copyfile(primer_bed, version_dir / "primer.bed")
    # Copy the amplicon.bed file
    shutil.copyfile(amplicon_bed, version_dir / "amplicon.bed")
    # Copy the msa
    shutil.copyfile(msa, version_dir / msa.name)
    # Copy the licenseassets/LICENSE
    shutil.copyfile(pathlib.Path("assets/LICENSE"), version_dir / "LICENSE")

    ## Copy accessory filess
    # Create a work dir
    work_dir = version_dir / "work"
    work_dir.mkdir()

    # copy the config file
    shutil.copyfile(conf, work_dir / "config.json")
    # copy the logfile
    shutil.copyfile(logfile, work_dir / "output.log")

    # copy the pngs
    for png in pngs:
        shutil.copyfile(png, work_dir / png.name)

    # Create a scheme README.md
    with open(version_dir / "README.md", "w") as scheme_readme:
        scheme_readme.write(f"# {primal_nf_scheme_dir.name} {version}\n\n")

        ## Add the interactive links
        scheme_readme.write(
            f"### [Interactive page](https://chrisgkent.github.io/schemes/{primal_nf_dir.name}-{size}-{version})\n\n"
        )

        # Add a quick descriptions
        scheme_readme.write(f"### Description\n\n")
        scheme_readme.write(
            f"This is an autogenerated scheme for TAXID: [{taxid}](https://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?mode=Info&id={taxid}&lvl=3&lin=f&keep=1&srchmode=1&unlock)\n\nGenomes are scraped from the EBI API, and then filtered, phylogenetically downsampled and aligned, to produce the input for a new PrimalScheme algorithm\n\nFor details please see preprint: TBD\n\n"
        )

        scheme_readme.write(f"### Scheme Overview\n\n")
        # Add links to the pngs
        for png in pngs:
            scheme_readme.write(f"![Alt text](work/{png.name} '{png.name}')\n\n")

        # Add the footer
        scheme_readme.write(LICENSE_TXT)

    # Create the md page for jekyll
    md_path = create_md(
        html_figs=htmls,
        bed_file=primer_bed,
        config=conf,
        outdir=md_outdir,
        scheme_name=primal_nf_scheme_dir.name,
        url=f"{primal_nf_dir.name}-{size}-{version}",
    )


def main():
    args = cli()
    dryrun = args.dryrun
    # Get the outdirs
    md_outdir: pathlib.Path = args.mdoutdir
    scheme_outdir = args.schemeoutdir
    # get the input dir
    primal_nf_dirs = args.schemedir
    # get some params
    size = str(args.size)
    version = args.version

    for primal_nf_dir in primal_nf_dirs:
        scheme_name = primal_nf_dir.name
        create(
            scheme_outdir=scheme_outdir,
            md_outdir=md_outdir,
            primal_nf_dir=primal_nf_dir,
            size=size,
            version=version,
            scheme_name=scheme_name,
            pclass=args.pclass,
        )


if __name__ == "__main__":
    main()
