"""LinkedIn の分析の書き出し（Excel）を読み、投稿の数字をまとめて出す（LOG386）。

使い方: python3 analyze_linkedin.py <LinkedIn から書き出した xlsx>

LinkedIn の「アナリティクス」→ 投稿のインプレッション →「エクスポート」で書き出したファイルを読む。
シートは 調査 / エンゲージメント / 最新の投稿 / 人気の投稿 / フォロワー / オーディエンス統計データ / コンテンツ統計データ。
数字は文字列で入っているので int に直して使う。
"""
import collections
import sys
import urllib.parse

import openpyxl


def rows(ws):
    return [r for r in ws.iter_rows(values_only=True) if any(c not in (None, "") for c in r)]


def post_name(url):
    """投稿の URL から、本文の書き出し（LinkedIn が URL に入れた語）を読める形にする"""
    tail = url.split("/posts/eiichi-shimazu_", 1)[-1]
    tail = urllib.parse.unquote(tail)
    for sep in ("-share-", "-ugcPost-", "-activity-"):
        tail = tail.split(sep, 1)[0]
    return tail.replace("-", " ")[:40]


def main(path):
    wb = openpyxl.load_workbook(path, data_only=True)

    print("## 期間全体")
    for r in rows(wb["調査"]):
        print(" ", " / ".join(str(c) for c in r if c is not None))

    print("\n## 月ごとのインプレッションと反応")
    daily = [(d, int(i), int(e)) for d, i, e in rows(wb["エンゲージメント"])[1:]]
    month = collections.OrderedDict()
    for d, i, e in daily:
        y, m, _ = d.split("/")
        k = f"{y}/{int(m):02d}"
        month.setdefault(k, [0, 0, 0])
        month[k][0] += i
        month[k][1] += e
        month[k][2] += 1
    print("  月       日数  インプレッション  反応  1日あたり")
    for k, (i, e, n) in month.items():
        print(f"  {k}  {n:>4}  {i:>14}  {e:>4}  {i / n:>8.1f}")

    print("\n## インプレッションが多かった日（上位10日）")
    for d, i, e in sorted(daily, key=lambda x: -x[1])[:10]:
        print(f"  {d:<11} インプレッション {i:>4}  反応 {e:>2}")

    print("\n## 反応が付いた日（反応1以上）")
    for d, i, e in daily:
        if e:
            print(f"  {d:<11} インプレッション {i:>4}  反応 {e:>2}")

    top = rows(wb["人気の投稿"])[2:]
    by_eng = [(r[0], r[1], int(r[2])) for r in top if r[0]]
    by_imp = [(r[4], r[5], int(r[6])) for r in top if r[4]]

    print(f"\n## 反応の多い投稿（{len(by_eng)}本・LinkedIn が出した全件）")
    for n, (u, d, e) in enumerate(by_eng, 1):
        print(f"  {n:>2}. {d:<10} 反応 {e:>2}  {post_name(u)}")

    print(f"\n## インプレッションの多い投稿（{len(by_imp)}本・LinkedIn が出した全件）")
    for n, (u, d, i) in enumerate(by_imp, 1):
        print(f"  {n:>2}. {d:<10} {i:>4}  {post_name(u)}")

    eng = [e for _, _, e in by_eng]
    print("\n## 反応の数ごとの投稿の本数（反応の多い投稿の一覧から）")
    for k, v in sorted(collections.Counter(eng).items(), reverse=True):
        print(f"  反応 {k:>2}: {v}本")

    print("\n## 最新の投稿（LinkedIn が出した直近3本・ネットワークの内と外の割合つき）")
    head, *body = rows(wb["最新の投稿"])
    for r in body:
        print(f"  - {post_name(r[0])}")
        for h, v in zip(head[1:], r[1:]):
            print(f"      {h}: {v}")

    print("\n## フォロワー")
    fr = rows(wb["フォロワー"])
    print(" ", " / ".join(str(c) for c in fr[0]))
    fmonth = collections.OrderedDict()
    for d, n in fr[2:]:
        y, m, _ = d.split("/")
        k = f"{y}/{int(m):02d}"
        fmonth[k] = fmonth.get(k, 0) + int(n)
    for k, v in fmonth.items():
        print(f"  {k} 新規 {v}人")
    print(f"  期間の合計 新規 {sum(fmonth.values())}人")

    for name in ("オーディエンス統計データ", "コンテンツ統計データ"):
        print(f"\n## {name}（{'フォロワーの内訳' if name.startswith('オーディエンス') else '投稿を見た人の内訳'}）")
        for r in rows(wb[name])[1:]:
            print(f"  {r[0]:<6} {r[1]:<28} {r[2]}")


if __name__ == "__main__":
    main(sys.argv[1])
