"""
Generate the dailyb spam, run from RUN_12Z.sh
"""

import os
import pathlib
import re
import smtplib
import subprocess
from datetime import datetime, timedelta, timezone
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from zoneinfo import ZoneInfo

import click
import httpx
import wwa
from pyiem.database import get_dbconnc, sql_helper, with_sqlalchemy_conn
from pyiem.reference import ISO8601
from pyiem.util import exponential_backoff, logger, utc
from sqlalchemy.engine import Connection

LOG = logger()
REPOS = (
    "iem pyiem iemone iemlsr iemvtec pywwa iem-database iem-web-services"
).split()
GITHUB_API_BASE = "https://api.github.com/repos/akrherz"
URLS = re.compile(r"(https?://[\w\d:#@%/;$()~_?\+-=\\\.&]*)", re.MULTILINE)


def mywrap(text):
    """Make text pretty, my friends"""
    text = text.replace("\n\n", "\n").replace("\n", "\n    ").rstrip()
    return text


def htmlize(msg):
    """Convert things into html."""
    for token in URLS.findall(msg):
        msg = msg.replace(token, f'<a href="{token}">{token}</a>')
    return msg


def get_github_commits():
    """Get the recent day's worth of github code commits

    Returns:
      txt (str): text variant result
      html (str): html variant result
    """
    utcnow = utc()
    yesterday = utcnow - timedelta(hours=24)
    yesterday = yesterday.replace(hour=12, minute=0, second=0)
    iso = yesterday.strftime(ISO8601)

    txt = ["> IEM Code Pushes <repo,branch> on Github\n"]
    html = """
<h3 style="font-family: Arial, sans-serif; color: #333;">
IEM Code Pushes &lt;repo,branch&gt; on Github</h3>

<table style="width: 100%; border-collapse: collapse;">
<thead><tr style="background-color: #f2f2f2;">
<th style="border: 1px solid #ddd; padding: 8px;">Timestamp</th>
<th style="border: 1px solid #ddd; padding: 8px;">Repository</th>
<th style="border: 1px solid #ddd; padding: 8px;">Message</th>
<th style="border: 1px solid #ddd; padding: 8px;">Link</th>
</tr></thead>
<tbody>
    """

    links = []
    for repo in REPOS:
        uri = f"{GITHUB_API_BASE}/{repo}/commits?since={iso}&sha=main"
        try:
            resp = httpx.get(uri, timeout=30)
            resp.raise_for_status()
            commits = resp.json()[::-1]
        except Exception as exp:
            LOG.info("Exception fetching %s", uri)
            LOG.exception(exp)
        # commits are in reverse order
        for commit in commits:
            if commit["commit"]["message"].startswith("Merge"):
                LOG.info("Skipping merge commit %s", commit["sha"])
                continue
            if commit["commit"]["author"]["name"].startswith("dependabot"):
                LOG.info("Skipping dependabot commit %s", commit["sha"])
                continue
            timestring = commit["commit"]["author"]["date"]
            utcvalid = datetime.strptime(timestring, ISO8601)
            valid = utcvalid.replace(tzinfo=timezone.utc).astimezone(
                ZoneInfo("America/Chicago")
            )
            data = {
                "stamp": valid.strftime("%b %-d %-2I:%M %p"),
                "msg": commit["commit"]["message"],
                "htmlmsg": htmlize(commit["commit"]["message"])
                .replace("\n\n", "\n")
                .replace("\n", "<br />\n"),
                "branch": "main",
                "url": commit["html_url"][:-20],  # chomp to make shorter
                "i": len(links) + 1,
                "repo": repo,
            }
            links.append("[%(i)s] %(url)s" % data)
            txt.append(
                mywrap(
                    "  %(stamp)s[%(i)s] <%(repo)s,%(branch)s> %(msg)s" % data
                )
            )
            html += (
                """
<tr>
<td style="border: 1px solid #ddd; padding: 8px;">%(stamp)s</td>
<td style="border: 1px solid #ddd; padding: 8px;">
<a href="https://github.com/akrherz/%(repo)s"
 style="color: #007bff; text-decoration: none;">%(repo)s,main</a></td>
<td style="border: 1px solid #ddd; padding: 8px;">%(htmlmsg)s</td>
<td style="border: 1px solid #ddd; padding: 8px;">
<a href="%(url)s" style="color: #007bff; text-decoration: none;">Link</a></td>
</tr>"""
                % data
            )

    if len(txt) == 1:
        txt = txt[0] + "    No code commits found in previous 24 Hours"
        html += """
<tr>
<td colspan="4"
 style="border: 1px solid #ddd; padding: 8px; text-align: center;">
<strong>No code commits found in previous 24 Hours</strong>
</td>
</tr>
        """
    else:
        txt = "\n".join(txt) + "\n\n" + "\n".join(links)
    html += "</tbody></table>"

    return f"{txt}\n\n", f"{html}<br /><br />"


def cowreport():
    """Generate something from the Cow, moooo!"""
    central = ZoneInfo("America/Chicago")
    yesterday = (utc() - timedelta(days=1)).astimezone(central)
    midnight = yesterday.replace(hour=0, minute=0)
    midutc = midnight.astimezone(ZoneInfo("UTC"))
    begints = midutc.strftime("%Y-%m-%dT%H:%M")
    endts = (midutc + timedelta(hours=24)).strftime("%Y-%m-%dT%H:%M")
    api = (
        f"http://iem.local/api/1/cow.json?begints={begints}&endts={endts}&"
        "phenomena=SV&phenomena=TO&lsrtype=SV&lsrtype=TO"
    )
    data = httpx.get(api, timeout=60).json()
    st = data["stats"]
    if st["events_total"] == 0:
        text = "No SVR+TOR Warnings Issued."
        html = f"<h3>IEM Cow Report</h3><pre>{text}</pre>"
        txt = f"> IEM Cow Report\n{text}\n"
        return txt, html

    vp = st["events_verified"] / float(st["events_total"]) * 100.0
    text = (
        f"SVR+TOR Warnings Issued: {st['events_total']:3.0f} "
        f"Verified: {st['events_verified']:3.0f} [{vp:.1f}%]\n"
        "Polygon Size Versus County Size            "
        f"[{st['size_poly_vs_county[%]']:.1f}%]\n"
        "Average Perimeter Ratio                    "
        f"[{st['shared_border[%]']:.1f}%]\n"
        "Percentage of Warned Area Verified (15km)  "
        f"[{st['area_verify[%]']:.1f}%]\n"
        "Average Storm Based Warning Size           "
        f"[{st['avg_size[sq km]']:.0f} sq km]\n"
        f"Probability of Detection(higher is better) [{st['POD[1]']:.2f}]\n"
        f"False Alarm Ratio (lower is better)        [{st['FAR[1]']:.2f}]\n"
        f"Critical Success Index (higher is better)  [{st['CSI[1]']:.2f}]\n"
    )

    html = f"<h3>IEM Cow Report</h3><pre>{text}</pre>"
    txt = f"> IEM Cow Report\n{text}\n"

    return txt, html


def feature():
    """Print the feature for yesterday"""
    mesosite, mcursor = get_dbconnc("mesosite")
    lastts = datetime.now() + timedelta(days=-1)
    # Query
    mcursor.execute(
        "SELECT *, to_char(valid, 'DD Mon HH:MI AM') as nicedate "
        "from feature WHERE date(valid) = 'YESTERDAY'"
    )
    textfmt = """
 +----------------------------------------------
%(link)s
 | Title : %(title)s
 | Date  : %(nicedate)s
 | Votes : Good: %(good)s   Bad: %(bad)s   Abstain: %(abstain)s
 +---------------------------------------------------------------

%(story)s
"""
    htmlfmt = """
<p><a href="%(link)s">%(title)s</a>
<br /><strong>Date:</strong> %(nicedate)s
<br /><strong>Votes:</strong> Good: %(good)s &nbsp;
Bad: %(bad)s  Abstain: %(abstain)s
<br />%(mediamarkup)s

<p>%(story)s</p>
"""
    txt = "> Daily Feature\n"
    html = "<h3>Daily Feature</h3>"

    for row in mcursor:
        row2 = row.copy()
        row2["link"] = (
            "https://mesonet.agron.iastate.edu/onsite/features/"
            f"cat.php?day={lastts:%Y-%m-%d}"
        )
        imgurl = (
            "https://mesonet.agron.iastate.edu/onsite/features/"
            f"{row['valid']:%Y/%m/%y%m%d}.{row['mediasuffix']}"
        )
        if row["mediasuffix"] == "mp4":
            row2["mediamarkup"] = (
                f'<video controls><source src="{imgurl}" type="video/mp4">'
                "Your email client does not support videos, please follow "
                "the link from the title of this feature to view.</video>"
            )
        else:
            row2["mediamarkup"] = f'<img src="{imgurl}">'
        if row2["appurl"] is not None:
            if not row2["appurl"].startswith("http"):
                row2["appurl"] = (
                    "https://mesonet.agron.iastate.edu" + row2["appurl"]
                )
            textfmt += (
                "\n\nThe featured media can be generated here: %(appurl)s"
            )
            htmlfmt += (
                "<p>The featured media can be generated on-demand "
                '<a href="%(appurl)s">here</a></p>.'
            )
        txt += textfmt % row2
        html += htmlfmt % row2
    if mcursor.rowcount == 0:
        txt += "\n    No feature posted\n\n"
        html += "<strong>No feature posted</strong>"

    mesosite.close()
    return txt, html


def news():
    """Print the news that is fit to print"""
    mesosite, mcursor = get_dbconnc("mesosite")
    # Last dailyb delivery
    lastts = datetime.now() + timedelta(days=-1)
    mcursor.execute(
        "SELECT *, to_char(entered, 'DD Mon HH:MI AM') as nicedate "
        "from news WHERE entered > %s ORDER by entered DESC",
        (lastts,),
    )

    textfmt = """
 +----------------------------------------------
 | Title : %(title)s
 | Date  : %(nicedate)s
 | Author: %(author)s
 | URL   : %(url)s
 +----------------------------------------------

%(body)s

"""
    htmlfmt = (
        "<hr />\n"
        "<br /><strong>Title:</strong>\n"
        '<a href="https://mesonet.agron.iastate.edu/'
        'onsite/news.phtml?id=%(id)s">%(title)s</a>\n'
        "<br /><strong>Date:</strong> %(nicedate)s\n"
        "<br /><strong>Author:</strong> %(author)s\n"
        '<br /><a href="%(url)s">link</a>\n\n'
        "<p>%(body)s\n"
    )
    txt = "> News\n"
    html = "<h3>News</h3>"

    for row in mcursor:
        txt += textfmt % row
        html += htmlfmt % row
    if mcursor.rowcount == 0:
        txt += "\n    No news is good news\n\n"
        html += "<strong>No news is good news</strong>"

    mesosite.close()
    return txt, html


def send_email(msg):
    """Send emails"""
    smtp = smtplib.SMTP("mailhub.iastate.edu")
    smtp.sendmail(msg["From"], [msg["To"]], msg.as_string())
    smtp.quit()


@with_sqlalchemy_conn("iembot")
def iembot_report(conn: Connection | None = None) -> list[str, str]:
    """Return on IEMBot stats."""
    txt = """
> IEMBot Social Media Posts

IEMBot can be configured to post messages to a number of social media services.
More details: https://mesonet.agron.iastate.edu/projects/iembot/

Posts yesterday per supported service:

"""
    html = """
<h3>IEMBot Social Media Posts</h3>

<p>
IEMBot can be configured to post messages to a number of social media
services. More details:
<a href="https://mesonet.agron.iastate.edu/projects/iembot/">
IEMBot Homepage</a>.
</p>

<p>Posts yesterday per supported service:</p>
<ul>
"""
    res = conn.execute(
        sql_helper("""
    select service, count(*) from iembot_social_log l JOIN iembot_accounts a
    on (l.iembot_account_id = a.id) where valid > 'YESTERDAY'
    and valid < 'TODAY' group by service order by service
                   """)
    )
    labels = {
        "slack": "Slack",
        "xmpp": "Weather.IM Jabber Chatrooms",
        "webhook": "HTTP Webhooks",
        "atmosphere": "ATMosphere (bluesky only attm)",
        "mastodon": "Mastodon / Fediverse",
        "twitter": "Twitter/X",
    }
    for row in res.mappings():
        label = labels.get(row["service"], row["service"])
        txt += f"  {label}: {row['count']:,}\n"
        html += f"<li><strong>{label}:</strong> {row['count']:,}</li>\n"

    html += "</ul>"
    return txt, html


@click.command()
@click.option("--dryrun", is_flag=True, help="Do not send email, just print")
def main(dryrun: bool):
    """Go Main!"""
    msg = MIMEMultipart("alternative")
    now = datetime.now()
    msg["Subject"] = f"IEM Daily Bulletin for {now:%b %-d %Y}"
    msg["From"] = "daryl herzmann <akrherz@iastate.edu>"
    if os.environ["USER"] == "akrherz2":
        msg["To"] = "akrherz@iastate.edu"
    else:
        msg["To"] = "iem-dailyb@googlegroups.com"

    text = f"Iowa Environmental Mesonet Daily Bulletin for {now:%d %B %Y}\n\n"
    html = (
        f"<h3>Iowa Environmental Mesonet Daily Bulletin for {now:%d %B %Y}"
        "</h3>\n"
    )

    t, h = news()
    text += t
    html += h
    try:
        t, h = get_github_commits()
        text += t
        html += h
    except Exception as exp:
        LOG.info("get_github_commits failed with %s", exp)
        text += "\n(script failure fetching github activity\n"
        html += "<br />(script failure fetching github activity<br />"
    t, h = feature()
    text += t
    html += h
    t, h = wwa.run()
    text += t
    html += h
    try:
        t, h = cowreport()
        text += t
        html += h
    except Exception as exp:
        LOG.exception(exp)

    # IEMBot stats
    t, h = iembot_report()
    text += t
    html += h

    part1 = MIMEText(text, "plain")
    part2 = MIMEText(html, "html")
    msg.attach(part1)
    msg.attach(part2)

    if not dryrun:
        LOG.info("Sending email to %s", msg["To"])
        exponential_backoff(send_email, msg)

    # Send forth LDM
    pathlib.Path("tmp.txt").write_text(text, encoding="utf-8")
    subprocess.call(
        [
            "pqinsert",
            "-p",
            "plot c 000000000000 iemdb.txt bogus txt",
            "tmp.txt",
        ]
    )
    pathlib.Path("tmp.html").write_text(html, encoding="utf-8")
    subprocess.call(
        [
            "pqinsert",
            "-p",
            "plot c 000000000000 iemdb.html bogus txt",
            "tmp.html",
        ]
    )
    if not dryrun:
        for suffix in ["txt", "html"]:
            os.unlink(f"tmp.{suffix}")


if __name__ == "__main__":
    main()
